在我的应用程序中,我有类似的东西:
public enum Locations {
LocationA,
LocationB,
LocationC
}
private List<Locations> _myLocations;
public Int64 PackedLocations {
get {
return PackEnumList(this._myLocations);
}
}
所以:枚举(由int支持),这些枚举值的List,以及一个只读属性,它返回到目前为止我遗漏的方法的结果。
该方法PackEnumList旨在给我一个64位整数,其中每个BIT表示在唯一枚举值列表中是否选择了相应的枚举值。所以在我上面的例子中,如果_myLocations只有一个项目:{Locations.LocationA},结果将是1(二进制:... 00001),如果我们然后将Locations.LocationC添加到该列表,结果将是5(二进制:... 000101)。现在实施并不重要(但我会在下面将其包括在内以获得完成/兴趣/反馈),但该方法的签名是:
public Int64 PackEnumList(List<Enum> listOfEnumValues) {
...
}
当我编译时,我收到一个错误“最好的重载方法......有一些无效的参数”。
我猜这是因为_myLocations被视为一个int值列表,但我希望PackEnumList()能够工作,即使所使用的枚举由其他东西支持,如果可能的话。
是否有更合适的方法来创建一个接受任何枚举的List / Collection的方法?
为了完整性,这是我正在尝试做的其余部分(这些是静态的,因为它们位于共享实用程序类中)。这些都是完全未经测试的(因为我在调用pack方法时无法通过编译错误),所以请带上一粒盐。并且可能有更好的方法来实现这一点,我正在这一半解决一个有趣的问题,一半因为我认为这是一个有趣的问题。
public static Int64 PackEnumList(List<Enum> listOfEnumValues) {
BitArray bits = new BitArray(64, defaultValue: false);
foreach (var value in listOfEnumValues) {
// get integer value of each Enum in the List:
int val = Convert.ToInt32(value);
if (val >= 64) {
// this enum has more options than we have bits, so cannot pack
throw new Exception("Enum value out of range for packing: " + val.ToString());
}
bits[val] = true;
}
var res = new Int64[1];
bits.CopyTo(res, 0);
return res[0];
}
// (this method is a little farther from the ideal: the resulting list will need
// to be matched by the caller to the appropriate List of Enums by casting
// each Int32 value to the Enum object in the list)
public static List<Int32> UnpackEnumList(Int64 packedValue) {
string binaryString = Convert.ToString(packedValue, 2);
List<Int32> res = new List<Int32>();
for (int pos = 0; pos < binaryString.Length; pos++) {
if (binaryString[binaryString.Length - pos - 1] == '1') {
// bit is on
res.Add(pos);
}
}
return res;
}
答案 0 :(得分:4)
是否有更合适的方法来创建一个接受任何枚举的List / Collection的方法?
直接C#?不。但你可以捏造它......
我有一个名为Unconstrained Melody的项目,它允许你创建一个约束为&#34的泛型方法; T必须是一个枚举类型&#34;或者&#34; T必须是委托类型&#34;。这些是IL级别的有效约束,但不能用C#
表示基本上无约束的旋律由两部分组成:
(期望图书馆的用户只是使用重写的二进制文件。)
听起来你可以在这里使用项目的后半部分代码。它不会非常愉快,但它会起作用。您可能还会发现库部件很有用。
总的来说,您可能需要考虑使用[Flags]
式枚举:
[Flags]
public enum Locations {
LocationA = 1 << 0,
LocationB = 1 << 1,
LocationC = 1 << 2
}
答案 1 :(得分:1)
将您的方法签名更改为public Int64 PackEnumList(IEnumerable<Enum> listOfEnumValues)
然后称之为:
public Int64 PackedLocations
{
get { return PackEnumList(this._myLocations.Cast<Enum>()); }
}
答案 2 :(得分:1)
List<Enum>
不是List<Locations>
,也不是List<Int32>
。使用通用方法处理列表:
public static void PackEnumList<T>(IEnumerable<T> list) where T : IConvertible
{
foreach (var value in list)
int numeric = value.ToInt32();
// etc.
}
答案 3 :(得分:0)
我会将您的签名方法更改为:
public Int64 PackEnumList<T>(IEnumerable<T> listOfEnumValues) where T : struct, IFormattable, IConvertible {
...
}
where T:struct ...仅限于枚举类型(任何其他实现两个接口的结构,可能非常低)