为什么ref参数不是逆变的?

Jan*_*ter 4 c# ref contravariance

这有效:

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

但这不是:

IPEndPoint endPoint = new IPEndPoint(_address, _port);
_socket.ReceiveFrom(buffer, 0, 1024, SocketFlags.None, ref endPoint);
Run Code Online (Sandbox Code Playgroud)

(注意endPoint的类型)

这似乎很奇怪.为什么ref关键字会破坏参数的逆转?

Tho*_*que 17

因为在方法签名中,endPoint参数声明为EndPoint,而不是IPEndPoint; 无法保证该方法不会设置endPoint为另一种EndPoint不可分配给IPEndPoint变量的方法.

例如,假设您有一个FooEndPoint继承自的类EndPoint,以及一个Fooref EndPoint参数的方法:

public class FooEndPoint : EndPoint
{
   ...
}

public void Foo(ref EndPoint endPoint)
{
    ...
    endPoint = new FooEndPoint();
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果你能够将a传递IPEndPoint给该方法,那么a 参数的FooEndPoint分配endPoint将在运行时失败,因为a FooEndPoint不是IPEndPoint