为什么我不能将String func(SomeEnum)转换为Func <enum,string =“”>?</enum,>

时间:2011-10-26 19:07:53

标签: c# .net-4.0 func

认为这与整个方差有关,但我不明白为什么不允许这样做。

我有一个方法

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);
}

4 个答案:

答案 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)

这里有两个问题:

  1. 您的转化期望协方差,但Func<in T, out TResult>实际上是第一个通用参数的逆变。您无法将 特定枚举类型的方法视为可以对任何枚举类型进行操作的方法。如果我们尝试使用其他任意枚举类型实例调用委托,您会发生什么?

  2. 即使您解决了第一个问题(可能是通过撤消转换?),这也行不通。变体转换可以很好地与装箱转换相匹配 - 来自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