Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can´t have two methods with same signature but different generic constraints

Tags:

c#

generics

I have this method:

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) 
    where TResult : AnotherType

Now I want this method to also appear for IEnumerable<AnotherType>. So I wrote this which apparently doesn´t compile:

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) 
    where TResult : IEnumerable<AnotherType>

I get the compiler-error:

Member with the same signature already declared

I read Member with the same signature already defined with different type constraints which deals members with another return-type. However in my example I don´t distinguish on the methods return-type but on its param-list which is Func<MyType, TResult> in the first place and Func<IEnumerable<MyType>, TResult> in the second one. However the compiler can´t handle this.

Is there another way than having another method-name for the second example?

like image 530
MakePeaceGreatAgain Avatar asked Dec 21 '16 09:12

MakePeaceGreatAgain


1 Answers

It is true that two method overloads are not allowed to differ solely by the generic constraint.

In your case I wonder if you even need TResult (as was also commented by Alfie Goodacre) becuause IEnumerable<out T> is covariant in T and Func<in T1, out TResult> is covariant in TResult.

So try:

public IEnumerable<MyType> DoSomething(Func<MyType, AnotherType> func) 

and:

public IEnumerable<MyType> DoSomething(Func<MyType, IEnumerable<AnotherType>> func) 

Because of the mentioned covariances, it will be fine to use a class more derived than AnotherType when calling the above overloads.


Another option:

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, TResult> func) 
  where TResult : AnotherType

and:

public IEnumerable<MyType> DoSomething<TResult>(Func<MyType, IEnumerable<TResult>> func) 
  where TResult : AnotherType

In this alternative approach, the signatures differ and the constraint is the same in both overloads. This can work even if AnotherType is an interface and TResult is a struct (value type) implementing the interface, a situation in which covariance (out T and out TResult) does not work.

like image 172
Jeppe Stig Nielsen Avatar answered Sep 23 '22 14:09

Jeppe Stig Nielsen