简体   繁体   English

Linq to objects - 选择第一个对象

[英]Linq to objects - select first object

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 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

@FryHard FirstOrDefault will work but remember that it returns null if none are found. @FryHard FirstOrDefault可以工作,但请记住,如果没有找到它,它将返回null。 This code isn't tested but should be close to what you want: 此代码未经过测试,但应接近您的要求:

var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);

if (app == null)
    return;

SetForegroundWindow(app.MainWindowHandle);

Do not use Count() like ICR says. 不要使用Count()一样ICR说。 Count() will iterate through the IEnumerable to figure out how many items it has. Count()将遍历IEnumerable以计算它有多少项。 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() Count is almost never a good idea. Count几乎从来都不是个好主意。

There are several problems with FryHard's answer. FryHard的答案有几个问题。 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 . 首先,由于执行延迟 ,您将最终执行两次LINQ查询,一次获取结果数,一次获得FirstOrDefault Second, there is no reason whatsoever to use FirstOrDefault after checking the count. 其次,在检查计数后没有任何理由使用FirstOrDefault Since it can return null, you should never use it without checking for null. 因为它可以返回null,所以不应该在不检查null的情况下使用它。 Either do apps.First().MainWindowHandle or: 要么做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获得所需内容的最有效和最稳定的方式。

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 );
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM