2017-07-06 1 views
0

Ich muss die Methode für jedes Element in der Liste aufrufen. So habe ich Where<> Abfrage wie folgt verwendet,Prädikat in einer Where <> Abfrage nicht getroffen?

List<string> list = new List<string>(); 
list.Add("Name1"); 
list.Add("Name2"); 
list.Add("Name3"); 

var name = list.Where(n => 
{ 
    return CheckName(n); 
}); 

Aber im obigen Fall wird CheckName() nicht getroffen. Die gleiche Methode wird ausgelöst, wenn ich FirstOrDefault<> verwende. Ich weiß nicht, ob es sich um eine Rahmenpause handelt oder ich verfahre falsch.

Als zusätzliche Informationen verwende ich .NET Framework 4.5.

Hat jemand diesen Fehler erlebt? Wenn ja, gibt es eine Lösung, um dieses Problem zu lösen?

+3

Verzögerte Ausführung von LINQ. Wie wäre es, wenn Sie am Ende eine '.ToList()' hinzufügen? –

+0

Die CheckName-Methode wird nur ausgeführt, wenn Sie name variabl angeben. Seine aufgerufen differed Ausführung –

Antwort

3

Sie verstehen das Ergebnis des Where Zustandes falsch. Da linq ausgeführt wird, wird sie nur dann in den Wo-Zustand eingegeben, wenn sie materialisiert ist (durch eine ToList/FirstOrDefault/Sum und so).

Die Where ist nie wirklich in Ihrem aktuellen Code materialisiert (Es tat, wie Sie bei der Verwendung erfahren) und als solche wird es nie die CheckName Methode eingeben. Dann, als Where wird nie null zurückgeben, aber "worst case" eine leere Sammlung, die nicht null ist, ist das Ergebnis true.

Wenn Sie debuggen Sie sehen, dass nametrue am Ende dieser entspricht.Um „zu überwinden“ hängt davon ab, was Ihre gewünschte Ausgabe:

  1. Wenn Sie wollen wissen, ob Sie ein Element, das das Prädikat abgestimmt dann:

    var result = list.Any(CheckName); 
    
  2. Wenn Sie diejenigen abrufen dass das Prädikat entsprechen:

    var result = list.Where(CheckName); 
    

    wenn Sie später abfragen möchten und prüfen, ob results alles enthält dann:

    if(result.Any()) { /* ... */ } 
    

    Wenn Sie nur die Ergebnisse (und damit der Abfrage materialisiert):

    list.Where(CheckName).ToList(); 
    

Lesen Sie mehr über Linq hier ausgeführt DEFFERED werden:


Genau wie eine Randnotiz zu sehen, wie Sie Ihren aktuellen Code aus ändern können:

var name = list.Where(n => 
{ 
    return CheckName(n); 
}) 

An:

var name = list.Where(n => CheckName(n)); 

Und schließlich:

var name = list.Where(CheckName); 
+0

Ich habe den folgenden Code verwendet, var name = list.Where (n => CheckName (n)); Trotzdem wird die CheckName() Methode nicht ausgeführt. – Divakar

+0

@Divakar - ja - wie ich erklärt habe, müssen Sie die Abfrage materialisieren. Verwenden Sie 'ToList' zum Beispiel –

+0

@Divakar - siehe Update –

2

LINQ hat a Verzögerte Ausführung prin cipal, was bedeutet, dass die Abfrage erst ausgeführt wird, wenn Sie auf die Variable name zugreifen. Wenn Sie es sofort ausführen möchten, (nur zum Beispiel) fügen Sie am Ende .ToList() hinzu, was genau das ist, was tut. Es führt sofortige Ausführung statt verzögerter Ausführung aus.

var name = list.Where(n => 
{ 
    return CheckName(n); 
}).ToList() != null; 

Auch where Bedingung Ergebnis wird nie null sein. Auch wenn es in list kein Objekt gibt, das Ihre Bedingung (en) in CheckName erfüllt, gibt where eine leere Sammlung zurück.

1

Die Methode CheckName() wird wegen der verzögerten Ausführung von Linq nicht ausgeführt. Die eigentliche Anweisung wird erst ausgeführt, wenn Sie tatsächlich darauf zugreifen. Also in Ihrem Fall für die CheckName(), sollten Sie so etwas wie:

var name = list.Where(n => 
{ 
    return CheckName(n); 
}).ToList(); 
+0

Was fügt Ihre Antwort über mehrere andere Antworten hinzu, die dasselbe sagen? –

0

Wenn Sie eine Methode für jedes Element in einer Liste anrufen müssen, dann sollten Sie eine einfache for-Schleife:

foreach var name in list 
    CheckName(name); 

Nur weil LINQ verfügbar ist, bedeutet es nicht, dass es überall dort verwendet werden sollte, wo es eine Sammlung gibt.Es ist wichtig, Code zu schreiben, der Sinn macht und sich selbst kommentiert. Die Verwendung dieses Codes hat gleichzeitig einen Fehler in Ihrer Logik verursacht und Ihren Code schwerer lesbar, verständlich und pfleglich gemacht. Es ist das falsche Werkzeug für den angegebenen Zweck

Zweifellos haben Sie zusätzliche Anforderungen nicht hier angegeben, wie "Ich möchte jeden Namen in einer Liste überprüfen und sicherstellen, dass keine null sind". Sie können und möglicherweise sollte Linq dafür verwenden, aber es sieht eher wie

bool allNamesOK = list.All(n => n != null); 

Dieser Code ist kompakt und gut liest; können wir die Absicht klar sehen (obwohl ich nicht die Liste „Liste“ nennen würde - „Namen“ wäre besser)

0

Wenn Sie an der Sie Where -Methode source Code aussehen kann leicht sehen, warum:

internal static IEnumerable<T> Where<T>(this IEnumerable<T> enumerable, Func<T, bool> where) { 
     foreach (T t in enumerable) { 
      if (where(t)) { 
       yield return t; 
      } 
     } 
    } 

Die Ausbeute bewirkt, dass die Ausführung nur dann erfolgt, wenn tatsächlich auf die zurückgegebene IEnumerable<T> zugegriffen wird. Das nennt man verzögerte Ausführung.

Verwandte Themen