gpt4 book ai didi

c# - 为什么 Delegate.CreateDelegate 允许无效转换?

转载 作者:行者123 更新时间:2023-11-30 12:36:05 26 4
gpt4 key购买 nike

编辑:我在 microsoft connect::上提交了错误报告: 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 可以进行这种其他创建函数的方法所不允许的奇怪转换?更糟糕的是,更明智的转换是说 Int64Object都失败了。我意识到 StringComparison “延伸”Int32 , 但我认为这更像是一个编译器技巧,因为枚举扩展了 Enum类。

此外,此转换适用于 DynamicMethod.CreateDelegate ,还有。

编辑刚刚用 Nullable<Int32> 试了一下它不起作用,这令人困惑。我认为唯一的“免费”转换是 Enum类型到它们的基础类型,但为什么呢?

请注意,这不允许您将 int 实例方法(如 GetHashCode)转换为采用枚举类型的开放方法,这就是为什么我认为这是一个错误,因为行为不一致。

编辑:如果我们删除 test2 和 test3 行,我们就可以测试方法、委托(delegate)和“非法”委托(delegate)是否都按预期工作。

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()
{
}
}

最佳答案

这不是错误。始终可以将整型值类型转换为枚举,如 StringComparison。编译器通常需要强制转换,但您在这里绕过了编译器。就像在 C# 中一样,没有检查来验证整数值实际上委托(delegate)枚举值之一。

关于c# - 为什么 Delegate.CreateDelegate 允许无效转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3949313/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com