2016-08-30 2 views
2

Ich bin verwirrt über einige multiple Filter in Linq Abfrage.Bessere Art zu schreiben Linq Where Anweisung

So:

var OrderList = (from o in db.Order 
       where (o.OrderType == 1 && 
       (((o.Status & 1) != 0) || ((o.Status & 2) != 0))) 
       || (o.OrderType == 2 && 
       (((o.Status & 3) != 0) || ((o.Status & 4) != 0))) 
       orderby o.OrderID descending 
       select new 
       { 
        Name = o.Name 
       }).ToList(); 

Filter in Linq hässlich aussehen und nicht leicht zu lesen.

Haben Sie eine bessere Möglichkeit, dies umzuschreiben?

+0

Ihre Formatierung ist ziemlich schlecht, aber wenn Sie Ihre Bitwise 'int' durch eine Aufzählung ersetzen, werden Sie dies viel einfacher zu lesen, ermöglicht auch die Verwendung der' HasFlags'-Funktion https://msdn.microsoft.com/ en-us/library/system.enum.hasflag (v = vs.110) .aspx – MikeT

+0

Vielleicht könnten Sie es zu einer Methode machen? – slawekwin

+0

Ist das Entity Framework? –

Antwort

4

Unter der Annahme, dass Status ist ein numerischer Wert-Typ (wie int oder uint oder long etc ..) und hat keine benutzerdefinierte Implementierung des & Operators führen & eine bitweise UND mit seinen Operanden.

Also ((o.Status & 1) != 0) || ((o.Status & 2) != 0) ist das gleiche wie (o.Status & 3) != 0. Es prüft nur, ob mindestens eines der beiden niederwertigsten Bits gesetzt ist. (Beachten Sie, dass die Bits 30011 sind).

Dementsprechend (o.Status & 3) != 0) || (o.Status & 4) != 0 ist die gleiche wie (o.Status & 7) != 0 (die Bits 7 sind 0111).

So können Sie den Zustand dieses vereinfachen:

(o.OrderType == 1 && (o.Status & 3) != 0) || 
(o.OrderType == 2 && (o.Status & 7) != 0) 

Aber das ist nur eine Vereinfachung ... Ablesbarkeit liegt im Auge des Leser. Es kann zweckmäßig sein, ein enum für das Status Feld zu verwenden, anstatt:

[Flags] 
public enum States 
{ 
    FirstBit = 1, // use self-explaining names here 
    SecondBit = 2, 
    ThirdBit = 4 
} 

// condition 
(o.OrderType == 1 && (o.Status.HasFlag(States.FirstBit) || o.Status.HasFlag(States.SecondBit)) || 
(o.OrderType == 2 && (o.Status.HasFlag(States.FirstBit) || o.Status.HasFlag(States.SecondBit) || o.Status.HasFlag(States.ThirdBit))) 

Dies länger ist, kann aber mehr lesbar sein, wenn die Namen selbsterklärend sind.

+0

Sie sind richtig, dass in diesem Fall die '&' für bitweisen Vergleich verwendet wird, aber es ist ein wenig irreführend zu sagen, dass was ist & 'Do, vor allem als seine außer Kraft setzen – MikeT

+0

@MikeT Sie haben Recht, ich nahm an," Status "zu sein (so etwas wie) ein" int "und dass es keine Überlastungen sind. Ich fügte diese Annahme meiner Antwort hinzu. –

+0

Vielen Dank für Ihr Beispiel, es ist lesbarer. – LorenzoC

Verwandte Themen