Linq aux objets - sélectionnez le premier objet
-
08-06-2019 - |
Question
Je ne connais presque rien à Linq.
Je fais ça:
var apps = from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app;
Ce qui me donne tous les processus en cours qui correspondent à ces critères.
Mais je ne sais pas comment obtenir le premier.Les exemples que je peux trouver sur le net semblent impliquer que je dois le faire
var matchedApp = (from app in Process.GetProcesses()
where app.ProcessName.Contains( "MyAppName" ) && app.MainWindowHandle != IntPtr.Zero
select app).First();
ce qui me semble quelque peu moche, et lève également une exception s'il n'y a pas de processus correspondant.Existe-t-il une meilleure façon ?
MISE À JOUR
En fait, j'essaie de trouver le premier élément correspondant et j'appelle SetForegroundWindow
dessus
J'ai trouvé cette solution, qui me semble également laide et horrible, mais meilleure que ci-dessus.Des idées?
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
La solution
@FryHard FirstOrDefault fonctionnera mais n'oubliez pas qu'il renvoie null si aucun n'est trouvé.Ce code n'est pas testé mais devrait être proche de ce que vous souhaitez :
var app = Process.GetProcesses().FirstOrDefault(p => p.ProcessName.Contains("MyAppName") && p.MainWindowHandle != IntPtr.Zero);
if (app == null)
return;
SetForegroundWindow(app.MainWindowHandle);
Autres conseils
Faire pas utiliser Count()
comme le dit ICR. Count()
parcourra le IEnumerable
pour savoir combien d'articles il contient.Dans ce cas, la pénalité en termes de performances peut être négligeable puisqu'il n'y a pas beaucoup de processus, mais c'est une mauvaise habitude à prendre.Seule utilisation Count()
lorsque votre requête ne s'intéresse qu'au nombre de résultats. Count
n'est presque jamais une bonne idée.
La réponse de FryHard pose plusieurs problèmes.D’abord, à cause de exécution retardée, vous finirez par exécuter la requête LINQ deux fois, une fois pour obtenir le nombre de résultats et une fois pour obtenir le FirstOrDefault
.Deuxièmement, il n'y a aucune raison d'utiliser FirstOrDefault
après avoir vérifié le décompte.Puisqu'il peut renvoyer null, vous ne devez jamais l'utiliser sans vérifier null.Soit faire apps.First().MainWindowHandle
ou:
var app = apps.FirstOrDefault();
if (app != null)
SetForegroundWindow(app.MainWindowHandle);
C'est pourquoi la meilleure solution est sans aucun doute celle de Mark.C'est le moyen le plus efficace et le plus stable d'utiliser LINQ pour obtenir ce que vous voulez.
En supposant que dans votre premier exemple d'applications il s'agisse d'un IEnumerable, vous pouvez utiliser les propriétés .Count et .FirstOrDefault pour obtenir l'élément unique que vous souhaitez transmettre à 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 );
}