C#,单个 T 和 IEnumerable 的重载<T>

问题描述 投票:0回答:4
public static void AddOrUpdate<T>(T entry) where T : class
{
        //stuff
}

public static void AddOrUpdate<T>(IEnumerable<T> entries) where T : class
{
    foreach (var entry in entries)
    {
        //stuff
    }

无论我向此方法发送什么内容,总是选择第一个。如何分离IEnmuerables和单个对象?

AddOrUpdate(entry); //goes into first one
AddOrUpdate(new Analog[] { entry}); //still goes into first one
c# object methods overloading ienumerable
4个回答
3
投票

因为第一个重载的定义指出,每当您在没有显式指向泛型参数 (

T
) 的情况下调用该方法时,该方法的参数与其泛型参数的类型相同(两者都是
AddOrUpdate(new Analog[] { entry })
类型),编译器决定类型匹配 -
AddOrUpdate<Analog[]>(new Analog[] { entry })
。 您需要显式地指向泛型参数以帮助编译器选择正确的重载:

AddOrUpdate<Analog>(new Analog[] { entry });

3
投票

鉴于您根本不想更改方法声明,我可以想到两种方法让编译器在调用方法时更喜欢第二种方法。

  • 指定通用参数:

    AddOrUpdate<Analog>(new Analog[] { entry });
    
  • 使参数为编译时类型

    IEnumerable<Analog>
    :

    IEnumerable<Analog> x = new Analog[] { entry };
    AddOrUpdate(x);
    // or
    AddOrUpdate(new string[] {""}.AsEnumerable());
    

1
投票

您还可以显式传入参数的类型:

AddOrUpdate(someEnumerable as IEnumerable<Analog>);

0
投票

这里更好的方法是测试方法中的类型。

AddOrUpdate<TorC>( TorC entryOrEntries)
{
    if (typeof(ToC).IsAssignableTo(typeof(IEnumerable)) {
        AddOrUpdateEnumerable( entryOrEntries);
    } else {
        AddOrUpdateSingle( entryOrEntries);
    }
}

这减少了无意的错误,因为调用者不必记住在传递值时指定类型。在另一种方法中,如果调用者忘记指定类型,那么编译器不会抱怨并且会调用错误的方法。

© www.soinside.com 2019 - 2024. All rights reserved.