Почему я не могу привести функцию String (SomeEnum) к функции?? - PullRequest
4 голосов
/ 26 октября 2011

Я думаю это как-то связано со всей дисперсией, но я не совсем понимаю, почему это не разрешено.

У меня есть метод

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)

Это действительно ужасно.

edit:

Я хочу сделать что-то подобное в методе(обратите внимание, в моем действительном коде enumType также передается как Type)

foreach (Enum val in Enum.GetValues(enumType))
{
      func(val);
}

Ответы [ 4 ]

3 голосов
/ 26 октября 2011

Вы могли бы сойти с рук

 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'

Так как вы не можете получить Enum2 из Enum1, вы застряли с инвариантными родовыми Enum s. Мудак.

2 голосов
/ 26 октября 2011

Вам не нужно создавать перегруженные методы, учтите:

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

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

Конечно, это ваша обязанность - принуждать / кастовать по необходимости.

Удачного кодирования.

2 голосов
/ 26 октября 2011

Здесь есть два вопроса:

  1. Ваше преобразование ожидает ковариации, но Func<in T, out TResult> на самом деле противоречиво по первому универсальному параметру. Вы не можете просмотреть метод, который работает с для a специфического типа перечисления как способ, который может работать с любым типом перечисления . Что вы ожидаете, если мы попытаемся вызвать делегат с другим произвольным экземпляром типа enum?

  2. Даже если вы обратились к первому вопросу (возможно, изменив конверсию?), Это не сработает. Преобразования вариантов не хорошо работают с преобразованиями в бокс - преобразование из someEnum -> System.Enum является таким преобразованием. См .: Почему делегирование контравариантности не работает с типами значений? для получения дополнительной информации.

1 голос
/ 26 октября 2011

Проблема в том, что класс Enum на самом деле не Enum, как вы думаете.Enum на самом деле не является производным от [Enum], и вы не можете выразить общее ограничение как Enum.

т.е. Func<T> where T : Enum недопустимо.

Лучше всего ограничить его, чтобы метод принимал только Enums:

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

...