Как я могу использовать linq, чтобы проверить, содержит ли перечисление flags / bitwise тип? - PullRequest
5 голосов
/ 07 октября 2010

следующий лямбда-оператор возвращает ноль, когда я надеялся, что он вернет строковое значение.

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

теперь свойство AddressType текущего экземпляра, который я запрашиваю, содержит следующие данные:

AddressType.Political | AddressType.Country

, поэтому он содержит ДВА значения.

Конечно, моя лямбда не будет работать, потому что значение страны (давайте предположим, что это 1)! = Значение Политического побитового или Страна (давайте предположим, что это 1 | 2 == 3).

Есть идеи?

Я волнуюсь, мне нужно что-то действительно ужасное, как ...

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

.. мысли?

Ответы [ 2 ]

8 голосов
/ 07 октября 2010

.NET 4.0 имеет метод Enum.HasFlag:

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

Если вы не используете .NET 4.0, битовая AND у вас есть хороший выбор. Если вам не нравится шаблон, посмотрите UnconstrainedMelody , в котором есть метод расширения для этой цели. Кроме того, вы можете написать один самостоятельно; этот вопрос, вероятно, поможет Кто-нибудь знает хороший обходной путь для отсутствия общего ограничения enum?

5 голосов
/ 13 октября 2010

Я призываю к осторожности с Enum.HasFlag в .NET 4.0. Когда я профилировал свое приложение с привязкой к вычислениям, используя ANTS 6.0, эта функция достигла вершины. Возвращаясь к старому ручному тестированию битовых флагов, я получил коэффициент ускорения> 100 в моем случае. Пока эта ошибка BCL не устранена, считайте, что вам советуют:

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.
    }
}
...