4

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

我有一个方法

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

4 回答 4

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,所以您会遇到不变的泛型Enums。臭虫。

于 2011-10-26T19:11:22.793 回答
2

这里有两个问题:

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

  2. 即使您解决了第一个问题(也许通过反转转换?),这也行不通。变体转换不能很好地与拳击转换一起使用 - 转换someEnum -> System.Enum就是这样的转换。请参阅:为什么委托逆变不能与值类型一起使用?了解更多信息。

于 2011-10-26T19:16:29.063 回答
2

您不需要创建重载方法,请考虑:

public void method(Func<Enum, string> func) {...}
public string doSomething(MyEnum e) {...}

method((Enum e) => doSomething((MyEnum)e));

当然,您有责任酌情强制/强制转换。

快乐编码。

于 2011-10-26T19:25:00.607 回答
1

问题是 Enum 类并不是你认为的真正的 Enum。Enum 并不是真正从 [Enum] 派生的,也不能将通用约束表示为 Enum。

即,Func<T> where T : Enum无效。

您最好的选择是将其限制为仅接受 Enums 的方法是:

Method<T>(Func<T, string> func) where T : struct, IConvertible

于 2011-10-26T19:18:38.220 回答