Привязать к объектам - выбрать первый объект

Я почти ничего не знаю о 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 ответа

Решение

@FryHard FirstOrDefault будет работать, но помните, что он возвращает ноль, если ничего не найдено. Этот код не проверен, но должен быть близок к тому, что вы хотите:

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 почти никогда не бывает хорошей идеей.

Есть несколько проблем с ответом Фрайхарда. Во-первых, из-за отложенного выполнения вы в конечном итоге выполните запрос LINQ дважды, один раз, чтобы получить количество результатов, и один раз, чтобы получить FirstOrDefault, Во-вторых, нет никаких оснований для использования FirstOrDefault после проверки счета. Поскольку он может возвращать ноль, вы никогда не должны использовать его без проверки на ноль. Либо сделать apps.First().MainWindowHandle или же:

var app = apps.FirstOrDefault();

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

Вот почему лучшее решение, без сомнения, от Марка. Это наиболее эффективный и стабильный способ использования LINQ, чтобы получить то, что вы хотите.

Предполагая, что в вашем первом примере приложения является 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 );
}
Другие вопросы по тегам