Search code examples
c#refcontravariance

Why are ref parameters not contravariant?


This works:

EndPoint endPoint = new IPEndPoint(_address, _port);
_socket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref endPoint);

But this does not:

IPEndPoint endPoint = new IPEndPoint(_address, _port);
_socket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref endPoint);

(Note the type of endPoint)

Which seems odd. Why does the ref keyword break parameter contravariance?


Solution

  • Because in the method signature, the endPoint parameter is declared as EndPoint, not IPEndPoint ; there is no guarantee that the method won't set endPoint to another kind of EndPoint, which would not be assignable to a IPEndPoint variable.

    For instance, assume you have a FooEndPoint class that inherits from EndPoint, and a Foo method that takes a ref EndPoint parameter :

    public class FooEndPoint : EndPoint
    {
       ...
    }
    
    public void Foo(ref EndPoint endPoint)
    {
        ...
        endPoint = new FooEndPoint();
        ...
    }
    

    If you were able to pass a IPEndPoint to that method, the assigment of a FooEndPoint to the endPoint parameter would fail at runtime, because a FooEndPoint is not a IPEndPoint