使用抽象类作为方法参数和使用泛型参数限定为该抽象类之间是否有明显的区别?

7

使用这两种方式有什么主要区别吗?

 public TValue SomeFunctionA<TValue>(BaseClass<TValue> bc)

结束

 public TValue SomeFunctionB<TValue, TBaseClass>(TBaseClass bc)
      where TBaseClass : BaseClass<TValue>

我已经进行了一些测试,似乎找不到任何区别。所有派生类都按照应该的方式表现(覆盖某些内容,新建某些内容等)。
如果“TValue”已知,例如(除了您现在可以使用运算符):
 public int SomeFunctionAInt(BaseClass<int> bc)

并且

 public int SomeFunctionBInt<TBaseClass>(TBaseClass bc)
      where TBaseClass : BaseClass<int>
1个回答

3
在这种情况下没有区别。泛型用于流动类型信息。一旦您想要调用其他代码,或者返回一个值,并且该值必须静态类型化为与输入参数bc相同,您就需要使用泛型。
例如,下面的两个函数输出相同的内容,但第二个保留了类型信息:
object PrintAndReturn1(object obj) { Console.WriteLine(obj); return obj; }
T PrintAndReturn2<T>(T obj) { Console.WriteLine(obj); return obj; }

当您想要保留类型信息时,泛型就会发挥作用。如果您只是消费一个值而不传递它,那么继承就足够了。

您说在测试过程中没有发现任何区别。这很有道理,因为JIT会擦除泛型类型信息(大多数情况下)。对于两种变体,JIT代码看起来非常相似。泛型类型的引用上的虚拟调用与非泛型v-calls的实现方式相同。(请注意,这仅适用于引用类型。所有引用类型共享一个JIT代码主体。)


1
从技术上讲,如果 obj 是一个结构体,你的两个函数将会有不同的行为。PrintAndReturn1 会将栈上的值装箱到堆上,或者 - 如果传递的值已经在堆上,因为它是某种引用类型 - 则指向它。PrintAndReturn2 总是会对传递的结构体进行浅复制,并返回另一个参数的浅复制。 - Tory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接