Вопрос

Я почти ничего не знаю о 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() как говорит МЦР. Count() будет перебирать IEnumerable чтобы выяснить, сколько в нем предметов.В этом случае снижение производительности может быть незначительным, поскольку процессов не так много, но это плохая привычка.Используйте только Count() когда ваш запрос интересует только количество результатов. Count почти никогда не является хорошей идеей.

С ответом FryHard есть несколько проблем.Во-первых, из-за отложенное исполнение, вам придется выполнить запрос LINQ дважды: один раз, чтобы получить количество результатов, и один раз, чтобы получить FirstOrDefault.Во-вторых, нет никаких оснований использовать FirstOrDefault после проверки счетчика.Поскольку он может возвращать значение NULL, никогда не следует использовать его без проверки на значение NULL.Либо сделай 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 );
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top