Can someone tell me what the difference is between the following
public class CarCollection<T>:List<T> where T:Car{}
and
public class CarCollection:List<Car>{}
To me they seem to do the same thing, create type-safe collection of "Car" objects.
Constraints are nice when you need some information about the generic type argument. By constraining the type you are not only limiting the set of valid type arguments but you are also giving yourself the ability to make compile-time decisions based on the common elements of that set of types.
In your specific example the generic constraint does not provide any benefit but in other circumstances they can. Consider this example:
T foo<T>()
{
return null;
}
This method cannot compile because the compiler knows (as well I should have when I wrote the method) that the generic type argument could possibly be a value type which cannot be set to null
. By adding a constraint I can make this code compile:
T foo<T>()
where T : class
{
return null;
}
I have now limited the valid set of generic type arguments to just classes. Since the compiler now knows that T
must be a class it allows me to return null
since there are no scenarios in which null
could not be returned. While this is not a terribly useful example I am sure you can extrapolate ways that this can be helpful.
If you implement a generic that will perform comparisons, the where clause is necessary. For example:
public class Foo<T> where T : IComparable<T>
{
public static void Bar(T blah, T bloo)
{
if(blah.CompareTo(bloo) < 0) //needs the constraint
Console.WriteLine("blee!");
}
}
This is a specific example, but it illustrates the concept that your where clause identifies that your generic type will adhere to a type, and thus is able to utilize functionality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With