Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any appreciable difference between using an abstract class as a method parameter and generic parameter constrained to said abstract class?

Is there any major difference between using

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

over

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

I've done some testing, and I can't seem to find any difference. All derived classes behave as they should (override something, new something, etc.).

What about if 'TValue' is known, such as (besides now you can use operators):

 public int SomeFunctionAInt(BaseClass<int> bc)

and

 public int SomeFunctionBInt<TBaseClass>(TBaseClass bc)
      where TBaseClass : BaseClass<int>
like image 678
Tory Avatar asked Dec 27 '13 15:12

Tory


1 Answers

In this case there is no difference. Generics are used to flow type information. As soon as you want to call other code, or return a value and that value must be statically typed to be the same as the input parameter bc, you need generics.

For example, the two functions below output the same thing, but the 2nd preserves type information:

object PrintAndReturn1(object obj) { Console.WriteLine(obj); return obj; }
T PrintAndReturn2<T>(T obj) { Console.WriteLine(obj); return obj; }

Generics come into play when you want to preserve type information. If you only ever consume a value and not pass it around, inheritance is enough.

You say you found no difference during testing. This makes sense because the JIT erases the generic type information (mostly). The JITed code will look very similar for both variants. Virtual calls on references of a generic type are implemented the same way as non-generic v-calls. (Note, that this goes for reference types only. All ref types share one JITed code body.)

like image 186
usr Avatar answered Oct 25 '22 10:10

usr