- Classes and structs can't be covariant, only interfaces and delegates are. This is a limitation of the CLR, so even adding a built-in type wouldn't solve this. Or are you proposing to change the CLR for this?
The prohibition on covariant structures is not merely a CLR limitation, but a semantic one:
- A class with covariant parameters cannot be type-safe if it has any mutable fields of any type involving
- For every structure type other than
Nullable<T> the run-time also defines a heap object type with
class semantics, whose fields are all mutable.
Semantically there would be no problem with an aggregate type that contained a field of a covariant generic type, if the aggregate could never be boxed as its own type. Unfortunately, there's no way to specify that an aggregate should behave in such fashion.
The biggest semantic obstacle to making
accept arbitrary covariant type parameters would be formulating suitable boxing and unboxing behavior for a
whose inner content would either be a null reference or is itself an empty
. Were it not for the convention of comparing
objects to null to test if they are empty, it would have been possible to say that an empty
will box as a singleton instance of class type
[a system-private sealed class with no fields derived from system-private
, which would compare equal to all instances of types derived from
with no value would box as
while one whose outer layer contains an empty
would box as
Despite the aforementioned difficulty, it would almost be possible to achieve workable semantics by having an empty
box as null while one that contained a null reference boxed as some non-empty-nullable-that-containings-null type. That would probably be workable but for one exception: the behavior of casting a
. Normally, casting a
should be equivalent to calling
. Unfortunately, it would be ambiguous as to whether casting a
was supposed to box it (which should yield null if the container is empty, or a non-empty-nullable-that-containings-null if it contained a null reference), or should yield
(which should throw an exception if the container is empty, or return
if it contains a null reference).
Since the inability to use a covariant type with
precludes the possibility of having an interface with covariant type
method that returns a
, perhaps what's needed is a means via which a
method could have a signature of the form:
T TryGetValue(someParameters, out bool gotValue)
but be marked with an attribute that would request the compiler to allow a friendlier caller-side syntax (e.g.
). That would allow many of the advantages of a covariant
without requiring CLR changes (the biggest weakness would be the inability to use the new syntax with existing collections without making code unusable with versions of the runtime that only support the covariance-hostile
bool TryGetValue(someParameters, out T value)