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();
}

现在,当我期望调用第二个函数时,第一个函数就会被调用。

C#关于泛型函数的更具体的版本

您需要添加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)