Why can't I use String func (SomeEnum) for Func <Enum, String>?

I think this has something to do with the whole mistake, but I don’t quite understand why this is not allowed.

I have a method

public void method(Func<Enum, String> func) 

And I have several different methods, such as

 public String doSomething(someEnum) public String doSomethingElse(someOtherEnum) 

I want to make such calls

 method(doSomething) method(doSomethingElse) 

but i get these errors

convert from 'method group' to System.Func<System.Enum,string>

What is the reason for this cannot be done? Do I really need to rewrite a method to several methods like this?

 public void method(Func<someEnum, String> func) public void method(Func<someOtherEnum, String> func) 

This is really ugly.

edit:

I want to do something like this in a method (note that in my actual code, enumType is also passed as a Type)

 foreach (Enum val in Enum.GetValues(enumType)) { func(val); } 
+4
source share
4 answers

You do not need to create overloaded methods, consider:

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

Of course, it is your responsibility to force / cast as necessary.

Happy coding.

+2
source

you could leave with

  public void method<TEnum>(Func<TEnum, String> func) 

or you can define a common delegate:

  delegate String MyFunc<T>(T); 

I think (have not tried) in C # 4.0 you can use co- / contravariance with this:

  delegate String MyFunc1<in T>(T); delegate String MyFunc2<out T>(T); 

This should mean that you could assign MyFunc<Derived> to MyFunc<Base>


Edit I just found out that covariance cannot be used for enumerations, since you cannot specify a type constraint:

 delegate string Display<in T>(T v) where T : Enum; 

Productivity:

  test.cs|5 col 50 error 702| A constraint cannot be special class `System.Enum' 

Since you cannot get Enum2 from Enum1, you are stuck with the invariant generic Enum s. Asshole.

+3
source

There are two questions here:

  • Your transformation expects covariance, but Func<in T, out TResult> is actually contravariant in the first generic parameter. You cannot view a method that works with a specific type of enumeration, like one that can work with any type of enumeration. What do you expect if you try to call a delegate with some other instance of the enum instance?

  • Even if you turned to the first question (perhaps by converting the conversion?), This will not work. Conversions of options do not go very well with conversions to boxing - the conversion from someEnum -> System.Enum is such a conversion. See Why is it not necessary to delegate contravariance work with type values? for more information.

+2
source

The problem is that the Enum class is not really the Enum you are thinking about. Enum is not actually derived from [Enum], and you cannot express a general restriction as Enum.

ie, Func<T> where T : Enum not valid.

It is best to limit it to the fact that the method only accepts Enums to have:

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

+1
source

All Articles