如果我将一个对象传递给一个方法,为什么我应该使用ref关键字?这难道不是默认的行为吗?

例如:

class Program
{
    static void Main(string[] args)
    {
        TestRef t = new TestRef();
        t.Something = "Foo";

        DoSomething(t);
        Console.WriteLine(t.Something);
    }

    static public void DoSomething(TestRef t)
    {
        t.Something = "Bar";
    }
}


public class TestRef
{
    public string Something { get; set; }
}

输出是“Bar”,这意味着对象作为引用传递。


当前回答

在. net中,当您将任何参数传递给方法时,将创建一个副本。在值类型中意味着您对值所做的任何修改都在方法范围内,并且在退出方法时丢失。

当传递一个引用类型时,也会生成一个副本,但它是一个引用的副本,也就是说,现在内存中有两个对同一个对象的引用。因此,如果你使用引用来修改对象,它就会被修改。但是如果您修改了引用本身——我们必须记住它是一个副本——那么任何更改也会在退出方法时丢失。

正如人们之前所说,赋值是对引用的修改,因此丢失了:

public void Method1(object obj) {   
 obj = new Object(); 
}

public void Method2(object obj) {  
 obj = _privateObject; 
}

上述方法不修改原始对象。

对你的例子做一点修改

 using System;

    class Program
        {
            static void Main(string[] args)
            {
                TestRef t = new TestRef();
                t.Something = "Foo";

                DoSomething(t);
                Console.WriteLine(t.Something);

            }

            static public void DoSomething(TestRef t)
            {
                t = new TestRef();
                t.Something = "Bar";
            }
        }



    public class TestRef
    {
    private string s;
        public string Something 
        { 
            get {return s;} 
            set { s = value; }
        }
    }

其他回答

Ref模仿(或行为)为两个作用域的全局区域:

调用者 调用。

将引用类型(例如List<T>)的变量(例如foo)视为持有形式为“object# 24601”的对象标识符。假设语句foo = new List<int> {1,5,7,9};使foo保存“Object #24601”(一个包含四个项的列表)。然后调用foo。Length将向object# 24601请求其长度,它将响应4,因此输入foo。长度等于4。

如果foo被传递给一个方法而没有使用ref,该方法可能会对Object #24601进行更改。作为这些变化的结果,foo。Length可能不再等于4。然而,方法本身将无法更改foo,它将继续保存“object# 24601”。

将foo作为ref参数传递将允许被调用的方法不仅对Object #24601进行更改,而且对foo本身进行更改。该方法可以创建一个新的对象#8675309,并在foo中存储对该对象的引用。如果这样做,foo将不再保存“object# 24601”,而是保存“object# 8675309”。

In practice, reference-type variables don't hold strings of the form "Object #8675309"; they don't even hold anything that can be meaningfully converted into a number. Even though each reference-type variable will hold some bit pattern, there is no fixed relationship between the bit patterns stored in such variables and the objects they identify. There is no way code could extract information from an object or a reference to it, and later determine whether another reference identified the same object, unless the code either held or knew of a reference that identified the original object.

但是,如果您传递的是一个值,情况就不同了。您可以强制通过引用传递值。例如,这允许您将一个整数传递给一个方法,并让该方法代表您修改该整数。

在. net中,当您将任何参数传递给方法时,将创建一个副本。在值类型中意味着您对值所做的任何修改都在方法范围内,并且在退出方法时丢失。

当传递一个引用类型时,也会生成一个副本,但它是一个引用的副本,也就是说,现在内存中有两个对同一个对象的引用。因此,如果你使用引用来修改对象,它就会被修改。但是如果您修改了引用本身——我们必须记住它是一个副本——那么任何更改也会在退出方法时丢失。

正如人们之前所说,赋值是对引用的修改,因此丢失了:

public void Method1(object obj) {   
 obj = new Object(); 
}

public void Method2(object obj) {  
 obj = _privateObject; 
}

上述方法不修改原始对象。

对你的例子做一点修改

 using System;

    class Program
        {
            static void Main(string[] args)
            {
                TestRef t = new TestRef();
                t.Something = "Foo";

                DoSomething(t);
                Console.WriteLine(t.Something);

            }

            static public void DoSomething(TestRef t)
            {
                t = new TestRef();
                t.Something = "Bar";
            }
        }



    public class TestRef
    {
    private string s;
        public string Something 
        { 
            get {return s;} 
            set { s = value; }
        }
    }

你需要区分“通过值传递引用”和“通过引用传递参数/参数”。

我写了一篇相当长的关于这个主题的文章,以避免每次在新闻组上出现这个问题时都要仔细写