我认为这与整个方差有关,但我不明白为什么不允许这样做。
我有一个方法
public void method(Func<Enum, String> func)
我有一些不同的方法,例如
public String doSomething(someEnum)
public String doSomethingElse(someOtherEnum)
我想像这样打电话
method(doSomething)
method(doSomethingElse)
但我收到了这些错误
从'方法组'转换为
System.Func<System.Enum,string>
这是不能做到的原因是什么?我是否真的需要将方法重写为多种方法?
public void method(Func<someEnum, String> func)
public void method(Func<someOtherEnum, String> func)
那太难看了。
编辑:
我想在方法中做这样的事情 (请注意,在我的实际代码中,enumType也作为Type传入)
foreach (Enum val in Enum.GetValues(enumType))
{
func(val);
}
答案 0 :(得分:3)
你或许可以逃脱
public void method<TEnum>(Func<TEnum, String> func)
或者您可以定义通用委托:
delegate String MyFunc<T>(T);
我认为(没有尝试过)在C#4.0中你可以使用共同/逆转:
delegate String MyFunc1<in T>(T);
delegate String MyFunc2<out T>(T);
这意味着您可以将MyFunc<Derived>
分配给MyFunc<Base>
编辑我刚刚发现确实无法使用协方差来处理枚举,因为您无法指定类型约束:
delegate string Display<in T>(T v) where T : Enum;
收率:
test.cs|5 col 50 error 702| A constraint cannot be special class `System.Enum'
因为你无法从Enum1派生出Enum2,所以你会遇到不变的通用Enum
。开溜。
答案 1 :(得分:2)
这里有两个问题:
您的转化期望协方差,但Func<in T, out TResult>
实际上是第一个通用参数的逆变。您无法将 特定枚举类型的方法视为可以对任何枚举类型进行操作的方法。如果我们尝试使用其他任意枚举类型实例调用委托,您会发生什么?
即使您解决了第一个问题(可能是通过撤消转换?),这也行不通。变体转换不可以很好地与装箱转换相匹配 - 来自someEnum -> System.Enum
的转换就是这样的转换。有关详细信息,请参阅:Why doesn't delegate contravariance work with value types?。
答案 2 :(得分:2)
您不需要创建重载方法,请考虑:
public void method(Func<Enum, string> func) {...}
public string doSomething(MyEnum e) {...}
method((Enum e) => doSomething((MyEnum)e));
当然,你有责任在适当的时候强迫/施放。
快乐的编码。
答案 3 :(得分:1)
问题是Enum类实际上不是你认为的Enum。 Enum并非真正来自[Enum],也不能将一般约束表达为Enum。
即,Func<T> where T : Enum
无效。
最好的办法是限制它让方法只接受Enums:
Method<T>(Func<T, string> func) where T : struct, IConvertible