2008-08-11 10 views
10

Ich weiß fast nichts über linq.Linq zu Objekten - wählen Sie das erste Objekt

Ich tue dies:

var apps = from app in Process.GetProcesses() 
    where app.ProcessName.Contains("MyAppName") && app.MainWindowHandle != IntPtr.Zero 
    select app; 

Was mich alle laufenden Prozesse wird die die Kriterien erfüllen.

Aber ich weiß nicht, wie man das erste bekommt. Die Beispiele, die ich im Netz finden kann scheinen zu implizieren ich diese

var matchedApp = (from app in Process.GetProcesses() 
    where app.ProcessName.Contains("MyAppName") && app.MainWindowHandle != IntPtr.Zero 
    select app).First(); 

zu tun haben, die mich als etwas hässlich trifft, und wirft auch eine Ausnahme, wenn es keine passenden Prozesse sind. Gibt es einen besseren Weg?

UPDATE

ich tatsächlich das erste passende Element zu finden versuchen, und rufen SetForegroundWindow darauf

ich mit dieser Lösung zu kommen haben, die als hässlich und schrecklich erscheint mir auch, aber besser als oben. Irgendwelche Ideen?

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 

Antwort

19

@FryHard FirstOrDefault wird funktionieren, aber denken Sie daran, dass es null zurückgibt, wenn keine gefunden werden. Dieser Code ist nicht getestet, sollte aber zu schließen, was Sie wollen:

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

if (app == null) 
    return; 

SetForegroundWindow(app.MainWindowHandle); 
+0

Wie Sie das als eine Abfrage und nicht eine Erweiterungsmethode? –

+2

@Quintin gibt es keine "Schlüsselwort" -Syntax für FirstOrDefault - Sie müssen die Erweiterungsmethode verwenden. –

+1

Nun, Sie könnten '(query) .FirstOrDefault()' aber die Erweiterungsmethode sentax ist einfacher zu lesen imo –

1

, dass in Ihrem ersten Beispiel Angenommen apps ist ein IEnumerable Sie Nutzung der .Count und .FirstOrDefault Eigenschaften machen könnte das einzelne Element, das Sie SetForegroundWindow übergeben wollen bekommen.

+1

wie an anderer Stelle erwähnt, das entfernt die Vorteile von linq (verzögerte Ausführung) und FirstOrDefault ist redundant mit einer Zählung –

2

Sie nicht Verwendung Count() wie ICR sagt. Count() wird durch die IEnumerable iterieren, um herauszufinden, wie viele Elemente es hat. In diesem Fall kann die Leistungseinbuße vernachlässigbar sein, da es nicht viele Prozesse gibt, aber es ist eine schlechte Angewohnheit, hineinzugehen. Verwenden Sie nur Count(), wenn Ihre Abfrage nur an der Anzahl der Ergebnisse interessiert ist.Count ist fast nie eine gute Idee.

Es gibt einige Probleme mit FryHards Antwort. Zuerst, wegen delayed execution, werden Sie am Ende die LINQ-Abfrage zweimal ausführen, einmal, um die Anzahl der Ergebnisse zu erhalten, und einmal, um die FirstOrDefault zu erhalten. Zweitens gibt es keinen Grund, nach Überprüfung der Zählung FirstOrDefault zu verwenden. Da es null zurückgeben kann, sollten Sie es niemals verwenden, ohne nach Null zu suchen. Entweder tun apps.First().MainWindowHandle oder:

var app = apps.FirstOrDefault(); 

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

Aus diesem Grund ist die beste Lösung Mark, ohne Frage. Es ist die effizienteste und stabilste Art, LINQ zu verwenden, um das zu erhalten, was Sie wollen.