C # more specific version about common function

I have the following function

public static T Translate<T>(T entity) { .... } 

Now, if T is en IEnumerable <> I want to have a different behavior, so I made a second function

 public static IEnumerable<T> Translate<T>(IEnumerable<T> entities) { .... } 

When I call him like that

 IEnumerable<string> test = new List<string>().AsEnumerable(); Translate(test); 

However, when I call him like that

 Func<IEnumerable<string>> func = () => new List<string>().AsEnumerable(); Translate(func.Invoke()) 

He goes to the first. Why is this happening and what is the best design to solve this problem?

UPDATE

I am creating a new example with a problem

 static void Main(string[] args) { Func<IEnumerable<string>> stringFunction = () => new List<string>().AsEnumerable(); InvokeFunction(ExtendFunction(stringFunction)); } private static T Convert<T>(T text) where T : class { return null; } private static IEnumerable<T> Convert<T>(IEnumerable<T> text) { return null; } private static Func<T> ExtendFunction<T>(Func<T> func) where T : class { return () => Convert(func.Invoke()); } private static T InvokeFunction<T>(Func<T> func) { return func.Invoke(); } 

The first function calls invoken now, when I expect the second to be called.

+5
source share
3 answers

You need to either add a second ExtendFunction overload:

 private static Func<IEnumerable<T>> ExtendFunction<T> (Func<IEnumerable<T>> func) where T : class { return () => Convert(func.Invoke()); } 

Or do the first overload by dynamically calling the Convert method:

 private static Func<T> ExtendFunction<T> (Func<T> func) where T : class { return () => Convert((dynamic)func.Invoke()); } 

The reason is because your ExtendFunction method selects the Convert method at compile time. You can either avoid adding a second ExtendFunction overload, which selects the Convert method that you need, or by moving the Convert method to start the time.

+7
source

In C #, the closest thing to specialization is to use a more specific overload; however, this only works when the type is known at compile time.

In your case, the type is determined at runtime due to IEnumerable<T> , but the compiler cannot guarantee that it will be IEnumerable<T> . If you add this line to your main method, you will get a second function. Convert(text: new List<string>().AsEnumerable());

this is because the type is known at compile time

so try your Main and see the differences.

 static void Main(string[] args) { Func<IEnumerable<string>> stringFunction = () => new List<string>().AsEnumerable(); InvokeFunction(ExtendFunction(stringFunction));//first function invoked Convert(text: new List<string>().AsEnumerable());//second function invoked } 
0
source

I had the same problem a few weeks ago. You can solve this problem by specifying the type explicitly on a method call, but it really is not worth it, because it means that everyone who uses your methods should be aware of this fact.

We solved our problem by actually giving the method a different name. In your case, this will be the second method named:

 public static IEnumerable<T> TranslateAll<T>(IEnumerable<T> entities) 
-1
source

Source: https://habr.com/ru/post/1201393/


All Articles