Linq到对象-选择第一个对象

时间:2020-03-05 18:38:53  来源:igfitidea点击:

我对linq几乎一无所知。

我正在这样做:

var apps = from app in Process.GetProcesses()
    where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
    select app;

这让我得到了所有符合该条件的正在运行的过程。

但是我不知道如何获得第一个。我可以在网上找到的示例似乎暗示我必须这样做

var matchedApp = (from app in Process.GetProcesses()
    where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
    select app).First();

这让我感到有些丑陋,如果没有匹配的流程,也会引发异常。有没有更好的办法?

更新

我实际上是在尝试找到第一个匹配项,然后在其上调用SetForegroundWindow

我想出了这个解决方案,它也使我感到丑陋和可怕,但比上面的要好。有任何想法吗?

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

解决方案

回答

假设在第一个示例应用程序中,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 );
}

回答

@FryHard FirstOrDefault可以使用,但是请记住,如果未找到,则它返回null。此代码未经测试,但应接近我们想要的代码:

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

if (app == null)
    return;

SetForegroundWindow(app.MainWindowHandle);