代码之家  ›  专栏  ›  技术社区  ›  Jan Bannister

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

  •  4
  • Jan Bannister  · 技术社区  · 16 年前

    这起作用:

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

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

    (注意端点的类型)

    这看起来很奇怪。为什么ref关键字会破坏参数逆变?

    3 回复  |  直到 16 年前
        1
  •  17
  •   Thomas Levesque    16 年前

    endPoint 参数声明为 EndPoint IPEndPoint ;无法保证该方法不会设置 端点 ,不可转让给 IPEndPoint 变量。

    例如,假设你有一个 FooEndPoint 继承自的类 端点 和a Foo 采用某种方法 ref EndPoint 参数:

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

    如果你能通过a IPEndPoint 对于这种方法,分配 FooEndPoint 端点 参数将在运行时失败,因为 FooEndPoint IPEndPoint

        2
  •  2
  •   Grzenio    16 年前

    因为ReceiveFrom方法可以创建新的端点,但不能创建IPEndPoint。此参数有两种工作方式,因此类型需要完全匹配。

        3
  •  0
  •   Davide Cannizzo    7 年前

    相反的趋势正在消失 ref out 参数,因为它们是引用。这意味着,当你向一个方法传递一个普通参数时,CLR将解析对一个值的引用,并将该值作为参数传递,而当一个参数是 参考 CLR将整个引用作为参数传递。中的引用类型。NET是 WeakReference<T> 你正在用它来包装你的参考。
    给出的通用论点 弱参考<T>

    public void Test<T>(ref T reference)
    {
        WeakReference<T> weakReference = __makeref(reference);
    }
    

    现在,我用另一个例子来深入探讨:

    public void Test(ref string reference)
    {
        WeakReference<string> weakReference = __makeref(reference);
    }
    

    还有一个:

    public void Test(ref string reference)
    {
        WeakReference<object> weakReference = __makeref(reference);
    }
    

    后一个例子会给你一个编译器错误:正如你所看到的,泛型参数不是逆变的。因此,当您将参数的引用包装到 弱参考<T> , T

    即使你不使用 __makeref ,您可以理解CLR的内部行为就是这样。

    推荐文章