【问题标题】:C#, overload for single T and for IEnumerable<T>C#,单个 T 和 IEnumerable<T> 的重载
【发布时间】:2020-08-11 06:17:04
【问题描述】:
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

【问题讨论】:

  • 可能有几种类型的类,这意味着我必须为所有这些类进行重载?好像不是很通用
  • 不,我显示的是调用者。
  • 使用AddOrUpdate&lt;IEnumerable&lt;Analog&gt;&gt;(...); 拨打电话。这是通用的。
  • 除非你显式地传递IEnumerable&lt;T&gt;,否则单项重载将是首选。这就是为什么框架有很多 AddRange 方法来避免这样的冲突。
  • 规范的整个部分都写了关于重载解析12.6.4 Overload resolution 进入更深入12.6.4.3 Better function member 因为你的类型不同它认为更通用的类型更好

标签: c# object methods overloading ienumerable


【解决方案1】:

因为第一个重载的定义表明,只要您在没有显式指向泛型参数的情况下调用该方法 (AddOrUpdate(new Analog[] { entry }) ) 编译器决定类型匹配 - AddOrUpdate&lt;Analog[]&gt;(new Analog[] { entry })。 您需要明确指出泛型参数以帮助编译器选择正确的重载:

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

【讨论】:

    【解决方案2】:

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

    • 指定泛型参数:

      AddOrUpdate<Analog>(new Analog[] { entry });
      
    • 制作编译时类型的参数IEnumerable&lt;Analog&gt;:

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

    【讨论】:

      【解决方案3】:

      你也可以显式传入参数的类型:

      AddOrUpdate(someEnumerable as IEnumerable<Analog>);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-22
        • 2012-06-23
        相关资源
        最近更新 更多