c# - 引用类型的ref修饰符

Max*_*Max 4 c#

我对这段代码感到有点困惑.

    public static void Foo(A p)
    {
        p.SomeProp = "ccc";
        p = null; // !!!
    }

    static void Main(string[] args)
    {
        A p = new A();
        Foo(p);

        Console.WriteLine("SomeProp is: " + p.SomeProp);
        Console.ReadLine();
    }
Run Code Online (Sandbox Code Playgroud)

输出是:

"SomeProp是:ccc "

但我本来期望一个NullReferenceException.


但是,如果我这样更改它,使用ref修饰符:

    public static void Foo(ref A p)
    {
        p.SomeProp = "ccc";
        p = null;
    }

    static void Main(string[] args)
    {
        A p = new A();
        Foo(ref p);

        Console.WriteLine("SomeProp is: " + p.SomeProp);
        Console.ReadLine();
    }
Run Code Online (Sandbox Code Playgroud)

我得到一个NullReferenceException - 第二个对我来说是可以理解的.

但是怎么可能,在第一段代码中p没有设置为null,但属性是否设置了它的值?

我的问题是:如果它不是对原始实例的引用,那么第一段代码中Foo方法的p参数是什么?


顺便说一句.这是A类的定义

public class A
{
    public string SomeProp;
}
Run Code Online (Sandbox Code Playgroud)

Joe*_*orn 17

在.Net中,除非您明确使用或关键字,否则所有内容都按值传递.对于引用类型,这意味着传递引用的副本. refout

在您的第一个示例中,这意味着您的p变量仍然是对同一对象的引用,因此设置属性的工作方式与您期望的一样.但是当你将引用本身设置为null时,所有你改变的都是副本.


ICR*_*ICR 5

p.SomeValue = "ccc";
Run Code Online (Sandbox Code Playgroud)

说:

  • 获取p是对其的引用的对象
  • 将该对象上的属性SomeValue的值设置为"ccc"

    p = null;

说:

  • 将p更改为,而不是引用它以前使用的对象,现在引用null.

它并不是说将p引用的对象更改为null,而是将局部变量p引用为null.

默认情况下,当您传递类型A的参数时,例如在方法调用"Foo(p)"中,您没有传递由p引用的对象,甚至是引用p,而是对p引用的对象的引用.它们引用相同的对象,但它们不是相同的引用.即,"public static void Foo(A p)"中的引用p与"Foo(p)"中的p不同,但它们引用相同的对象.

您可以使用ref参数来改变此行为.这会改变它以使它们相同的引用,并且改变一个的值会改变另一个的值.