Linq to objects - 选择第一个对象
-
08-06-2019 - |
题
我对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
解决方案
@FryHard FirstOrDefault 可以工作,但请记住,如果没有找到它,它会返回 null。此代码未经测试,但应该接近您想要的:
var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);
if (app == null)
return;
SetForegroundWindow(app.MainWindowHandle);
其他提示
做 不是 使用 Count()
就像 ICR 所说的那样。 Count()
将迭代 IEnumerable
找出它有多少个项目。在这种情况下,由于进程不多,性能损失可能可以忽略不计,但这是一个坏习惯。仅使用 Count()
当您的查询仅对以下内容感兴趣时 结果数量。 Count
几乎从来都不是一个好主意。
FryHard 的回答存在几个问题。首先,因为 延迟执行, ,您最终将执行 LINQ 查询两次,一次获取结果数,一次获取结果 FirstOrDefault
. 。其次,没有任何理由使用 FirstOrDefault
检查计数后。由于它可以返回 null,因此在不检查 null 的情况下切勿使用它。要么做 apps.First().MainWindowHandle
或者:
var app = apps.FirstOrDefault();
if (app != null)
SetForegroundWindow(app.MainWindowHandle);
这就是为什么最好的解决方案是马克的,毫无疑问。这是使用 LINQ 获得所需内容的最有效、最稳定的方式。
假设在您的第一个示例应用程序中,您可以使用 .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 );
}