2010-10-07 15 views
5

Comment utiliser linq pour vérifier si une énumération flags/bitwise contient un type? Le lambda statemement suivant renvoie null, alors que j'espérais qu'il retournerait une valeur de chaîne.

var countryCode = AddressComponents 
    .Where(x => x.AddressType == AddressType.Country) 
    .Select(x => x.ShortName) 
    .SingleOrDefault(); 

maintenant la propriété AddressType de l'instance actuelle, je suis interrigating contient les données suivantes:

AddressType.Political | AddressType.Country

il est donc contenant deux valeurs.

Bien sûr, mon lambda ne fonctionnera pas, parce que la valeur de country (supposons que c'est 1)! = La valeur de Political bitwise ou Country (supposons que c'est 1 | 2 == 3).

Des idées?

Je suis inquiet je dois avoir quelque chose de vraiment fraking laid comme ...

((AddressTypes & AddressType.Country) == AddressType.Country)

.. pensées?

Répondre

8

.NET 4.0 a la méthode Enum.HasFlag:

x => x.AddressType.HasFlag(AddressType.Country) 

Si vous n'êtes pas sur .NET 4.0, la AND vous avez bitwise il y a un bon choix. Si vous n'aimez pas le motif, consultez UnconstrainedMelody, qui a une méthode d'extension à cet effet. Alternativement, vous pouvez en écrire un vous-même; cette question sera probablement utile - Anyone know a good workaround for the lack of an enum generic constraint?

+0

SERIEUX ?!/brb .... HAHAHAH frak moi :) C'est aussi le cas! Gagner. gagner et el-winno-win !!! Qu'en est-il si vous voulez vérifier pour DEUX drapeaux. par exemple AddressType.Country ou AddressType.Foo? peut HasFlag (AddressType.Country) | AddressType.Foo) travail? * (remarquez le seul caractère PIPE) * –

+0

@ Pure.Krome: Oui, cela devrait fonctionner. De MSDN: "La méthode HasFlag renvoie le résultat de l'expression booléenne suivante: thisInstance Et flag = flag" – Ani

5

Je recommande la prudence avec Enum.HasFlag dans .NET 4.0. Lorsque j'ai profilé mon application liée au calcul, en utilisant ANTS 6.0, cette fonction est apparue près du sommet. Pour en revenir à l'ancien test de drapeau de bit manuel a donné un facteur de> 100 accélération dans mon cas. Jusqu'à ce que ce bug BCL soit résolu, considérez-vous conseillé:

using System; 
using System.Diagnostics; 

class Program 
{ 
    [Flags] enum test { flag1 = 1, flag2 = 2, flag4 = 4 } 

    static void Main(string[] args) 
    { 
     Stopwatch s; 
     test t = test.flag4; 

     s = Stopwatch.StartNew(); 
     for (int c=0,i=0; i < 50000000; i++) 
      if (t.HasFlag(test.flag2)) 
       c++; 
     Console.WriteLine(s.ElapsedMilliseconds); // 22837 ms. 

     s = Stopwatch.StartNew(); 
     for (int c=0,i=0; i < 50000000; i++) 
      if ((t & test.flag2) > 0) 
       c++; 
     Console.WriteLine(s.ElapsedMilliseconds); // 172 ms. 
    } 
} 
+0

Maintenant que c'est intéressant .... Je me demande si Jon + d'autres ont aucune connaissance de cela? –

+0

Malheureusement, c'est vrai, bien connu, et expliqué ici - http://www.codeproject.com/Tips/441086/NETs-Enum-HasFlag-and-performance-costs –