如何使用linq检查标志/按位枚举是否包含类型?

时间:2010-10-07 05:24:17

标签: .net linq enums lambda bit-manipulation

当我希望它返回一个字符串值时,以下lambda statemement返回null。

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

现在我正在进行interrigating的当前实例的AddressType属性包含以下数据:

AddressType.Political | AddressType.Country

所以它包含两个值。

当然,我的lambda不起作用,因为country的值(假设它是1)!= Political bitwise或Country的值(假设它是1 | 2 == 3)。

有什么想法吗?

我担心我需要一些像丑陋一样丑陋的东西......

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

..想法?

2 个答案:

答案 0 :(得分:8)

.NET 4.0具有Enum.HasFlag方法:

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

如果您不在.NET 4.0上,那么您所拥有的按位AND是一个不错的选择。 如果您不喜欢该模式,请查看UnconstrainedMelody,其中包含用于此目的的扩展方法。或者,你可以自己写一个;这个问题可能会有所帮助 - Anyone know a good workaround for the lack of an enum generic constraint?

答案 1 :(得分:5)

我敦促在.NET 4.0中使用Enum.HasFlag。当我使用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.
    }
}