【问题标题】:Defining method taking an IEnumerable - type constraint or base class?定义采用 IEnumerable 类型约束或基类的方法?
【发布时间】:2018-01-29 23:45:14
【问题描述】:

我之前问过一个关于using generic vs base class in a method taking in a List<T> 的问题。很快就有人指出,您不能将 List<Derived> 传递给需要 List<Base> 的方法。

进一步探索(以及有用的链接,例如 this one)表明,虽然您不能将 List<Derived> 传递给 List<Base>,但您可以List<Derived> 传递给 IEnumerable<Base>(由于 .NET 4 中的逆变/协方差。

就像我之前的问题一样,我在这里提出相同的问题:既然使用这两个选项似乎没有区别,那么哪个更好?它是严格地基于样式的东西,还是使用一个而不是另一个有影响?

选项 A:void DoWork<TBase>(IEnumerable<TBase> objs) where TBase : Base;

选项 B:void DoWork(IEnumerable<Base> objs);

【问题讨论】:

  • 选项 A 可以在方法中写入类似new TBase() 的内容......这只是一个立即浮现在脑海中的优势。
  • @HimBromBeere 您也可以将不同的类型添加到第一个集合中,使用Base 作为TBase
  • 确实,与使用List<T> 不同,使用IEnumerable<T> 将允许您将任何实现IEnumerable<X> 的实例发送到此方法,其中X 派生(或实现)T。所以对于什么更好的问题 - 好吧,在这种情况下,我认为这两种实现之间没有太大区别。 Generic 可能会生成更多编译代码,但我认为这并不重要。
  • @ViRuSTriNiTy 不,它不会 - 试试看。你会得到一个错误:Cannot create an instance of the variable type 'TBase' because it does not have the new() constraint。如果您将声明更改为where TBase : Base, new(),您可以使用new - 当然,您只能将它用于具有默认构造函数的类型。
  • @MatthewWatson 这是对的,只是忘了提。

标签: c# generics


【解决方案1】:

选项 A

void DoWork<TBase>(IEnumerable<TBase> objs) where TBase : Base;

IEnumerable 中的元素根据TBase 进行约束。如果TBase 继承自Base,则IEnumerable 不能包含Base

选项B

void DoWork(IEnumerable<Base> objs);

IEnumerable可以包含Base或任何继承自它的东西。

在任何一种情况下,除非有一些丑陋的类型检查,否则每个方法只能根据Base 的定义与IEnumerable 中的元素交互,因为这就是它“知道”它们的全部内容。

如果方法返回BaseTBase,差异会更有意义。然后调用者将能够传入TBase 并获得转换为TBase 的结果。如果类型对调用者的重要性大于对这个方法的重要性,那么它就不想传入一个继承自 TBase 的参数并将其结果转换为 Base

【讨论】:

    【解决方案2】:

    选项 A 稍微多一点,因为DoWork(new TDerived[0]) 是与DoWork(new TBase[0]) 不同的方法调用。抖动的输出中会有很多共享代码(因为TBaseTDerived 必须是引用类型才能真正不同,并且有一个派生自另一个),但这有点多余。

    理论上,如果DoWork 调用了一个虚拟方法并且TDerived 被密封,那么抖动有可能利用它会带来一点好处,但我很确定这不会发生,因为代码共享。如果真的发生了,差别将是微乎其微的。

    所以,在所有选项 B 中,没有 jitting 更多版本的泛型方法,选项 A 没有补偿优势。

    但是,如果是,选项 A 可能会更有用:

    TBase DoWorkAndReturnSomething(IEnumerable<TBase> objs) where TBase : Base
    

    避免强制转换结果的地方。如果您实际上正在投射结果,这将是一个真正的优势。如果您继续将其用作 Base 或将结果传递给采用 Base 的方法,那么您将无法弥补额外的抖动和额外的概念复杂性。

    因此,每种方法都有利有弊。对于更广泛的情况,非泛型可能会更好,但有时带有约束的泛型形式确实具有优势。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-22
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多