Linq to objects - 选择第一个对象

时间:2008-08-11 03:54:44

标签: c# linq linq-to-objects

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

3 个答案:

答案 0 :(得分:19)

@FryHard FirstOrDefault可以工作,但请记住,如果没有找到它,它将返回null。此代码未经过测试,但应该接近您的要求:

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

if (app == null)
    return;

SetForegroundWindow(app.MainWindowHandle);

答案 1 :(得分:2)

使用ICR所说的Count()Count()会遍历IEnumerable以确定它有多少项。在这种情况下,性能损失可以忽略不计,因为没有很多进程,但这是一个不好的习惯。仅当您的查询仅对结果数感兴趣时,才使用Count() Count几乎不是一个好主意。

FryHard的答案有几个问题。首先,由于delayed execution,您将最终执行两次LINQ查询,一次获取结果数,一次获得FirstOrDefault。其次,在检查计数后没有任何理由使用FirstOrDefault。因为它可以返回null,所以不应该在不检查null的情况下使用它。要么apps.First().MainWindowHandle,要么:

var app = apps.FirstOrDefault();

if (app != null)
    SetForegroundWindow(app.MainWindowHandle);

这就是为什么最好的解决方案是马克的,毫无疑问。这是使用LINQ获得所需内容的最有效和最稳定的方式。

答案 2 :(得分:0)

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