I have the following function
public static T Translate<T>(T entity)
{
....
}
Now if T is en IEnumerable<> I want to have a different behaviour so I made a second function
public static IEnumerable<T> Translate<T>(IEnumerable<T> entities)
{
....
}
When I invoke it like this
IEnumerable<string> test = new List<string>().AsEnumerable();
Translate(test);
However when I invoke it like this
Func<IEnumerable<string>> func = () => new List<string>().AsEnumerable();
Translate(func.Invoke())
It goes to the first one. Why does this happen and what is the best construction to solve this?
I build a new example with the 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 gets invoken now when I expect the second to be invoked.
You need to either add a second overload of ExtendFunction
:
private static Func<IEnumerable<T>> ExtendFunction<T> (Func<IEnumerable<T>> func) where T : class
{
return () => Convert(func.Invoke());
}
Or make the first overload invoke Convert
method dynamically:
private static Func<T> ExtendFunction<T> (Func<T> func) where T : class
{
return () => Convert((dynamic)func.Invoke());
}
The reason is that your ExtendFunction
method chooses Convert
method at compile time. You can avoid that be either adding a second overload of ExtendFunction
which chooses the Convert
method you need, or by moving the choice of Convert
method to run time.
In C#, the closest to specialization is to use a more-specific overload; however this works only when the type is know at compile time.
In your case the type is decided at run time because of IEnumerable<T>
, but the compiler cannot guarantee that it will be IEnumerable<T>
. If you add this line in your main method you'll get the second function called. Convert(text: new List<string>().AsEnumerable());
this is because the type is know at compile time
so try your Main in this way and look 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
}
I had the same problem a few weeks ago. You can solve this by specifying the type explicitely on calling the method but that's not really worth it, because it means everybody using your methods have to know about this fact.
We solved our problem by actually giving the method another name. In your case, that would be a second method named:
public static IEnumerable<T> TranslateAll<T>(IEnumerable<T> entities)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.