编辑:我在微软连接上提交了一个错误报告:: https://connect.microsoft.com/VisualStudio/feedback/details/614234/delegate-createdelegate-allows-binding-functions-with-enum-parameters-to-the-enum-base-type#details
考虑以下事项:
public static Int32 Test(Int16 @short)
{
return @short;
}
并且来自调用代码::
Func<Int16,Int32> test = Test; //valid method group conversion.
Func<Int16,StringComparison> test2 = Test; // doesn't compile, not valid method group conversion.
Func<Int16,StringComparison> test3 = test; // doesn't compile, invalid contra-variance.
Func<Int16,StringComparison> test4 = Delegate.CreateDelegate(typeof(Func<Int16,StringComparison>),test.Method) as Func<Int16,StringComparison>; // works fine.
为什么Delegate.CreateDelegate可以执行这种奇怪的转换,没有其他创建函数的方法允许?更糟糕的是,一个更合理的转换说Int64
或Object
都失败了。我意识到StringComparison
“扩展”Int32
,但我认为这更像是一个编译技巧,因为枚举扩展了Enum
类。
此外,此转换适用于DynamicMethod.CreateDelegate
。
编辑只是尝试使用Nullable<Int32>
它不起作用,这是令人困惑的。我认为唯一的“免费”转换是Enum
类型到它们的基础类型,但为什么呢?
请注意,这不允许您将int实例方法(如GetHashCode)转换为采用枚举类型的open方法,这就是为什么我认为这是一个错误,因为行为不一致。
编辑: 如果我们删除test2和test3行,那么我们可以测试看方法,委托和“非法”委托是否按预期工作。
Console.WriteLine(Test(0)); // prints 0
Console.WriteLine(test(0)); // prints 0
Console.WriteLine(test4(0)); //prints CurrentCulture
编辑:
这是我在大约10分钟内写的一个非常大的滥用。这为IEqualityComparer<T>
创建TEnum
,基本上抓取一个基础类型,然后只包装Equals,HashCode并使用此技巧/滥用将参数转换为TEnums,而不是基础类型。如果这是我想知道的错误,那么我就不会试图依赖这种行为。
class EnumComparer<TEnum> : EqualityComparer<TEnum> where TEnum : struct
{
static Func<TEnum, TEnum, bool> s_Equals;
static Func<TEnum, int> s_HashCode;
static EnumComparer<TEnum> s_default;
static EnumComparer()
{
if (!typeof(TEnum).IsEnum) throw new Exception("Not an enum type");
Type underlyingType = Enum.GetUnderlyingType(typeof(TEnum));
object equalityComparer = typeof(EqualityComparer<>).MakeGenericType(new[] { underlyingType }).GetProperty("Default").GetGetMethod().Invoke(null, null);
s_Equals = Delegate.CreateDelegate(typeof(Func<TEnum, TEnum, bool>), equalityComparer,equalityComparer.GetType().GetMethod("Equals", new[]{underlyingType,underlyingType})) as Func<TEnum,TEnum,bool>;
s_HashCode = Delegate.CreateDelegate(typeof(Func<TEnum, int>), equalityComparer, equalityComparer.GetType().GetMethod("GetHashCode", new[]{underlyingType})) as Func<TEnum, int>;
s_default = new EnumComparer<TEnum>();
}
public static new EnumComparer<TEnum> Default
{
get
{
return s_default;
}
}
public override bool Equals(TEnum x, TEnum y)
{
return s_Equals(x, y);
}
public override int GetHashCode(TEnum obj)
{
return s_HashCode(obj);
}
private EnumComparer()
{
}
}
答案 0 :(得分:2)
这不是错误。始终可以将整数值类型转换为类似StringComparison的枚举。编译器通常需要强制转换,但是你在这里绕过了编译器。就像在C#中一样,没有检查来验证积分值实际上是否代表枚举值之一。