C#关于泛型函数的更具体的版本
本文关键字:版本 函数 于泛型 泛型 | 更新日期: 2023-09-27 18:19:52
我有以下函数
public static T Translate<T>(T entity)
{
....
}
现在,如果T是en-IEnumerable<>我想有一个不同的行为,所以我做了第二个功能
public static IEnumerable<T> Translate<T>(IEnumerable<T> entities)
{
....
}
当我像这个一样调用它时
IEnumerable<string> test = new List<string>().AsEnumerable();
Translate(test);
然而,当我像这样调用时
Func<IEnumerable<string>> func = () => new List<string>().AsEnumerable();
Translate(func.Invoke())
它转到第一个。为什么会发生这种情况,解决这种情况的最佳方法是什么?
更新
我用问题构建了一个新的示例
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();
}
现在,当我期望调用第二个函数时,第一个函数就会被调用。
您需要添加ExtendFunction
:的第二个过载
private static Func<IEnumerable<T>> ExtendFunction<T> (Func<IEnumerable<T>> func) where T : class
{
return () => Convert(func.Invoke());
}
或者使第一个重载动态调用Convert
方法:
private static Func<T> ExtendFunction<T> (Func<T> func) where T : class
{
return () => Convert((dynamic)func.Invoke());
}
原因是您的ExtendFunction
方法在编译时选择了Convert
方法。您可以通过添加第二个ExtendFunction
重载来选择所需的Convert
方法,或者将Convert
方法的选择移动到运行时来避免这种情况。
在C#中,最接近专业化的是使用更具体的重载;但是,只有在编译时知道类型时,这才有效
在您的情况下,由于IEnumerable<T>
,类型是在运行时决定的,但编译器不能保证它将是IEnumerable<T>
。如果在主方法中添加这一行,则会调用第二个函数。Convert(text: new List<string>().AsEnumerable());
这是因为类型在编译时已知
所以用这种方式试试你的Main,看看的差异
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
}
几周前我也遇到了同样的问题。您可以通过在调用方法时明确指定类型来解决此问题,但这并不值得,因为这意味着每个使用您的方法的人都必须知道这一事实。
我们通过给这个方法起另一个名字来解决我们的问题。在您的情况下,这将是第二个名为的方法
public static IEnumerable<T> TranslateAll<T>(IEnumerable<T> entities)