C# Linq to objects - 选择第一个对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7503/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Linq to objects - select first object
提问by Orion Edwards
I know almost nothing about linq.
我对 linq 几乎一无所知。
I'm doing this:
我这样做:
var apps = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app;
Which gets me all the running processes which match that criteria.
这让我获得了符合该标准的所有正在运行的进程。
But I don't know how to get the first one. The examples I can find on the net seem to imply I have to do this
但我不知道如何获得第一个。我可以在网上找到的例子似乎暗示我必须这样做
var matchedApp = (from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app).First();
which strikes me as somewhat ugly, and also throws an exception if there are no matching processes. Is there a better way?
这让我觉得有些难看,如果没有匹配的进程也会抛出异常。有没有更好的办法?
UPDATE
更新
I'm actually trying to find the first matching item, and call SetForegroundWindow
on it
我实际上是在尝试找到第一个匹配项,然后调用SetForegroundWindow
它
I've come up with this solution, which also strikes me as ugly and awful, but better than above. Any ideas?
我想出了这个解决方案,这也让我觉得丑陋和可怕,但比上面的要好。有任何想法吗?
var unused = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select SetForegroundWindow( app.MainWindowHandle ); // side-effects in linq-query is technically bad I guess
采纳答案by Matt Hamilton
@FryHard FirstOrDefault will work but remember that it returns null if none are found. This code isn't tested but should be close to what you want:
@FryHard FirstOrDefault 将起作用,但请记住,如果未找到,它将返回 null。此代码未经测试,但应该接近您想要的:
var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);
if (app == null)
return;
SetForegroundWindow(app.MainWindowHandle);
回答by FryHard
Assuming that in your first example apps is an IEnumerable you could make use of the .Count and .FirstOrDefault properties to get the single item that you want to pass to SetForegroundWindow.
假设在您的第一个示例应用程序中是一个 IEnumerable,您可以使用 .Count 和 .FirstOrDefault 属性来获取要传递给 SetForegroundWindow 的单个项目。
var apps = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app;
if (apps.Count > 0)
{
SetForegroundWindow(apps.FirstOrDefault().MainWindowHandle );
}
回答by David Schwartz
Do notuse Count()
like ICR says. Count()
will iterate through the IEnumerable
to figure out how many items it has. In this case the performance penalty may be negligible since there aren't many processes, but it's a bad habit to get into. Only use Count()
when your query is only interested in the number of results.Count
is almost never a good idea.
不要像ICR所说的那样使用Count()
。Count()
将遍历IEnumerable
以找出它有多少项目。在这种情况下,性能损失可能可以忽略不计,因为进程并不多,但这是一个坏习惯。仅Count()
当您的查询仅对结果数量感兴趣时使用。Count
几乎从来都不是一个好主意。
There are several problems with FryHard's answer. First, because of delayed execution, you will end up executing the LINQ query twice, once to get the number of results, and once to get the FirstOrDefault
. Second, there is no reason whatsoever to use FirstOrDefault
after checking the count. Since it can return null, you should never use it without checking for null. Either do apps.First().MainWindowHandle
or:
FryHard 的回答有几个问题。首先,由于延迟执行,您最终将执行两次 LINQ 查询,一次是获取结果数量,一次是获取FirstOrDefault
. 其次,FirstOrDefault
检查计数后没有任何理由使用。因为它可以返回 null,所以你不应该在不检查 null 的情况下使用它。要么做,apps.First().MainWindowHandle
要么:
var app = apps.FirstOrDefault();
if (app != null)
SetForegroundWindow(app.MainWindowHandle);
This is why the best solution is Mark's, without question. It's the most efficient and stable way of using LINQ to get what you want.
这就是为什么最好的解决方案是马克,毫无疑问。这是使用 LINQ 获得所需内容的最有效和最稳定的方式。