Привязать к объектам - выбрать первый объект - PullRequest
10 голосов
/ 11 августа 2008

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

Ответы [ 3 ]

19 голосов
/ 11 августа 2008

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

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

if (app == null)
    return;

SetForegroundWindow(app.MainWindowHandle);
2 голосов
/ 19 ноября 2011

Делайте не используйте Count(), как говорит ICR. Count() будет перебирать IEnumerable, чтобы выяснить, сколько у него предметов. В этом случае снижение производительности может быть незначительным, поскольку не так много процессов, но это плохая привычка. Используйте Count() только тогда, когда ваш запрос интересует только число результатов. Count почти никогда не является хорошей идеей.

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

var app = apps.FirstOrDefault();

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

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

0 голосов
/ 11 августа 2008

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