Delegate Covariance and Contravariance using .NET 4.x Equivalent

According to this post by Microsoft the block of code below should work, but won’t even compile in Unity. Does Unity not support this, despite it being introduced in C# 4.0?

public class StartData : EventData
{
    public float Time;
}

public class TestClass : MonoBehaviour
{
    System.Action<EventData> _handler = null;

    private void Start()
    {
        _handler += TestCallback;
    }

    private void TestCallback(StartData startData)
    {
        Debug.Log("Testing");
    }
}

No this doesn’t work. You got the thing the other way round. The delegate has to have the more concrete parameter type while the actual handler hooked up can have a more abstract parameter type. So it would be save for the delegate to pass a “StartData” instance while the delegate receives an “EventData” instance. Since StartData is derived from EventData this works. However it doesn’t work the other way round. Imagine you have another class like this:

public class SomeOtherData : EventData
{
    public float FooBar;
}

Since your delegate parameter type is EventData it would be perfectly fine to pass a SomeOtherData instance to the delegate:

_handler(new SomeOtherData());

However you can not hook up a method with a more concrete parameter type as “SomeOtherData” can’t be casted to “StartData”.

Contravariance applies to parameters while Covariance applies to return types. The return type acts the other way round since the data flow is in the opposite direction. So the delegate can return an abstract / base data type while the actual handler hooked up can return a derived class, but not the other way round.

Make sure this is set unity doesn’t have it set to 4.x by default

123048-capture.png