Linq zu Objekten – erstes Objekt auswählen
-
08-06-2019 - |
Frage
Ich weiß fast nichts über Linq.
Ich mache das:
var apps = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app;
Dadurch erhalte ich alle laufenden Prozesse, die diesen Kriterien entsprechen.
Aber ich weiß nicht, wie ich an den ersten komme.Die Beispiele, die ich im Internet finden kann, deuten darauf hin, dass ich das tun muss
var matchedApp = (from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app).First();
Das kommt mir etwas hässlich vor und löst auch eine Ausnahme aus, wenn es keine passenden Prozesse gibt.Gibt es einen besseren Weg?
AKTUALISIEREN
Ich versuche tatsächlich, den ersten passenden Artikel zu finden und rufe an SetForegroundWindow
darauf
Ich habe mir diese Lösung ausgedacht, die mir ebenfalls hässlich und schrecklich vorkommt, 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
Lösung
@FryHard FirstOrDefault wird funktionieren, aber denken Sie daran, dass es null zurückgibt, wenn keine gefunden werden.Dieser Code wurde nicht getestet, sollte aber Ihren Wünschen nahe kommen:
var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);
if (app == null)
return;
SetForegroundWindow(app.MainWindowHandle);
Andere Tipps
Tun nicht verwenden Count()
wie ICR sagt. Count()
wird durch die iterieren IEnumerable
um herauszufinden, wie viele Elemente es enthält.In diesem Fall ist die Leistungseinbuße möglicherweise vernachlässigbar, da es nicht viele Prozesse gibt, aber es ist eine schlechte Angewohnheit, sich darauf einzulassen.Benutz nur Count()
wenn Ihre Anfrage nur an der interessiert ist Anzahl der Ergebnisse. Count
ist fast nie eine gute Idee.
Es gibt mehrere Probleme mit der Antwort von FryHard.Erstens, weil verzögerte Ausführung, führen Sie die LINQ-Abfrage am Ende zweimal aus, einmal, um die Anzahl der Ergebnisse zu erhalten, und einmal, um die zu erhalten FirstOrDefault
.Zweitens gibt es überhaupt keinen Grund für die Verwendung FirstOrDefault
nach Überprüfung der Zählung.Da es null zurückgeben kann, sollten Sie es niemals verwenden, ohne auf null zu prüfen.Entweder tun apps.First().MainWindowHandle
oder:
var app = apps.FirstOrDefault();
if (app != null)
SetForegroundWindow(app.MainWindowHandle);
Deshalb ist die beste Lösung ohne Frage die von Mark.Dies ist die effizienteste und stabilste Art, LINQ zu nutzen, um das zu bekommen, was Sie wollen.
Angenommen, dass es sich bei Ihren ersten Beispiel-Apps um ein IEnumerable handelt, könnten Sie die Eigenschaften .Count und .FirstOrDefault verwenden, um das einzelne Element abzurufen, das Sie an SetForegroundWindow übergeben möchten.
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 );
}