371 words
2 minutes
Understanding C# Covariance And Contravariance (8) Struct And Void

Understanding C# Covariance And Conreavariance:

Part 1 mentioned that variances do not work with struct and void.

Struct#

When we say Derived object “is a” Base object, it means the reference to a Derived object can be considered as a reference to a Base object.

But struct is value type. On the virtual machine described by CLI, when passing a struct value to a method receiving struct parameter, that value is copied and pushed to the stack. When returning a struct value from a method, that item is placed on the stack. We are not working with references.

Void#

The scenario of void looks special. On Microsoft Connect. Someone is asking for “Covariant return types should include void –> anything”.

It looks like anything can be covariant to void:

internal delegate void VoidOut();
internal delegate object ObjectOut();
internal class Program
{
private static void Main()
{
VoidOut voidOut = () => { };
ObjectOut objectOut = () => new object();
// It looks like covariance is Ok here.
voidOut = objectOut;
// Because when we invoke [void voidOut()], we are invoking [object objectOut()].
// The return value of [object objectOut()] can be just ignored.
voidOut();
}
}

There are also some people asking about the parameter:

internal delegate void NoParameterIn();
internal delegate void ObjectIn(object @object);
internal class Program
{
private static void Main()
{
NoParameterIn noParameterIn = () => { };
ObjectIn objectIn = (@object) => { };
// It looks like contravariance is Ok here.
objectIn = noParameterIn;
// Because when we invoke [void objectIn(object)], we are invoking [void noParameterIn()].
// The parameter of [void objectIn(object)] can be just ignored.
objectIn(new object());
}
}

Both of the above variance code cannot be compiled in C# 2.0 / 3.0 / 4.0. The reason is, on the virtual machine described by CLI, function with return value and function without return value work differently. If the variant is allowed, according to Eric Lippert:

we would be allowing you to misalign the IL stack!

Understanding C# Covariance And Contravariance (8) Struct And Void
https://dixin.github.io/posts/understanding-csharp-covariance-and-contravariance-8-struct-and-void/
Author
Dixin
Published at
2009-10-04
License
CC BY-NC-SA 4.0