Linq для объектов - выберите первый объект
Я почти ничего не знаю о 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();
который кажется мне несколько уродливым, а также генерирует исключение, если нет соответствующих процессов. Есть ли лучший способ?
UPDATE
Я на самом деле пытаюсь найти первый соответствующий элемент и называть 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
Ответы
Ответ 1
@FryHard FirstOrDefault будет работать, но помните, что он возвращает null, если ни один не найден. Этот код не проверен, но должен быть близок к тому, что вы хотите:
var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);
if (app == null)
return;
SetForegroundWindow(app.MainWindowHandle);
Ответ 2
Не используйте 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 для получения того, что вы хотите.
Ответ 3
Предполагая, что в первом примере приложения 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 );
}