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

时间:2014-08-29 07:27:03

标签: c# generics

我有以下功能

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

现在,如果T是IEnumerable&lt;&gt;我希望有不同的行为,所以我做了第二个功能

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

当我希望调用第二个函数时,第一个函数会立即被调用。

3 个答案:

答案 0 :(得分:7)

您需要添加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方法选择为运行时。

答案 1 :(得分:0)

在C#中,最接近专业化的是使用更具体的重载;但这只适用于在编译时知道类型的情况。

在您的情况下,由于IEnumerable<T>而在运行时决定类型,但编译器不能保证它将是IEnumerable<T>。 如果在main方法中添加此行,则会调用第二个函数。  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
}

答案 2 :(得分:-1)

几周前,我有same problem。您可以通过在调用方法时明确指定类型来解决此问题,但这并不值得,因为这意味着使用您的方法的每个人都必须知道这一事实。

我们通过实际给该方法另一个名称解决了我们的问题。在您的情况下,这将是第二个名为:

的方法
public static IEnumerable<T> TranslateAll<T>(IEnumerable<T> entities)