【问题标题】:Passing by reference and using ref通过引用传递和使用 ref
【发布时间】:2011-03-25 14:04:45
【问题描述】:

我查看了类似的问题并阅读了一些文章。 THis文章有一些图片说明了。

SomeObject so = new SomeObject();
somefunction(so);
Console.write(so.x); // will print 1

SomeObject so1 = new SomeObject();
somefunctionByRef(so1);
Console.write(so1.x); // will print 1


static void somefunction(SomeObject so)
{
    so.x = 1;
}

public void somefunctionByRef(ref SomeObject so)
{
    so.x = 1;
}

这两种方法对这个引用类型的效果是一样的。那么为什么要为引用类型选择ref 关键字呢?

使用 somefunction(SomeObject so) 并修改方法内的对象并期望更改而不使用 ref 关键字是一种不好的做法(可能是错误的)吗?

【问题讨论】:

    标签: c# .net parameters reference methods


    【解决方案1】:

    .Net中的默认参数传递是按值完成的。对于值类型和引用类型都是如此。不同之处在于,对于引用类型,您通过值与实际对象传递对实例的引用。

    效果是原函数中的so引用和someFunction是独立的。更改引用引用的实例对另一个实例没有影响。但是,因为它们引用同一个对象,所以它们可以看到另一个对象对该对象的突变(这就是 x 在您的示例中发生变化的原因)

    SomeObject so = new SomeObject();
    so.x = 42;
    somefunction(so);
    Console.Write(so.x); // will print 42
    
    static void somefunction(SomeObject so) {
      so = new SomeObject();
      so.x = 13;
    }
    

    ref 修饰符导致参数通过引用而不是值传递。实际上没有引用的副本,原始函数和调用函数中的so 是相同的引用。所以重置一个重置另一个

    SomeObject so = new SomeObject();
    so.x = 42;
    somefunction(ref so);
    Console.Write(so.x); // will print 13
    
    static void somefunction(ref SomeObject so) {
      so = new SomeObject();
      so.x = 13;
    }
    

    【讨论】:

      【解决方案2】:

      对于引用类型,默认情况下参数是通过引用传递的,除非指定按值传递。我认为这是一个足够安全的假设,大多数 .Net 开发人员都应该知道。

      【讨论】:

      • 默认都是通过value传递的。 value 在值类型(对象)和引用类型(对对象的引用)之间有所不同。 refout 允许通过引用传递。
      【解决方案3】:

      类已经通过引用传递(在非托管术语中,指向对象的指针也是如此)。传递引用使您可以更改基础变量(您正在使用指向指针的指针)。拿这个代码:

      static void foo(SomeObject so)
      {
          so.x = 1;
          so = null;
      }
      
      static void bar(ref SomeObject so)
      {
          so.x = 1;
          so = null;
      }
      
      SomeObject so1 = new SomeObject(); 
      foo(so1); 
      Console.write(so1.x); // will print 1 
      bar(so1); 
      Console.write(so1.x); // crash
      

      第一种方法将起作用,您将打印出 1 -- 将 so 分配给 null 只会更改函数本地的变量。第二个将导致崩溃(NullReferenceException),因为 so1 已设置为 null。

      【讨论】:

      • 那么为什么要为引用类型选择 ref 关键字呢?
      • 通过使用ref,您可以从不同的函数更改变量引用的对象。注意分配so = null;
      • 类不是通过引用传递的,它们实际上根本就没有传递。而是传递对类实例的引用,它们是按值传递的。
      【解决方案4】:

      我只在处理非引用类型时使用 ref,例如整数、小数等

      查看this MSDN page 以获得更清晰的解释,并了解一些问题

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-13
        • 1970-01-01
        • 2010-11-25
        • 1970-01-01
        • 1970-01-01
        • 2012-10-10
        • 2011-02-03
        • 1970-01-01
        相关资源
        最近更新 更多