我对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 );
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top