Why use the 'ref' keyword when passing an object?
如果要将对象传递给方法,为什么要使用ref关键字?这不是默认行为吗?
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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",这意味着对象被作为引用传递。
如果要更改对象是什么,请传递一个
1 2 3 4 5 6 7 8 9 |
调用dosomething后,
如果要更改不可变对象的值,例如
编辑:正如其他人提到的。除非需要,否则使用
此外,当参数类型为对象时,对象变量始终充当对对象的引用。这意味着当使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | int x = 1; Change(ref x); Debug.Assert(x == 5); WillNotChange(x); Debug.Assert(x == 5); // Note: x doesn't become 10 void Change(ref int x) { x = 5; } void WillNotChange(int x) { x = 10; } |
您需要区分"按值传递引用"和"按引用传递参数/参数"。
我写了一篇关于这个主题的相当长的文章,以避免每次出现在新闻组上时都要仔细地写:)
在.NET中,当您将任何参数传递给方法时,将创建一个副本。在值类型中,意味着对值所做的任何修改都在方法范围内,并且在退出方法时丢失。
当传递引用类型时,也会生成一个副本,但它是引用的副本,即现在在内存中有两个对同一对象的引用。因此,如果使用引用修改对象,它将被修改。但是,如果您修改引用本身(我们必须记住它是一个副本),那么在退出该方法时,任何更改都会丢失。
正如人们之前所说,任务是对引用的修改,因此会丢失:
1 2 3 4 5 6 7 | public void Method1(object obj) { obj = new Object(); } public void Method2(object obj) { obj = _privateObject; } |
上述方法不会修改原始对象。
稍微修改一下你的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | 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; } } } |
由于testref是一个类(它是引用对象),您可以在不将其作为引用传递的情况下更改t中的内容。但是,如果将t作为引用传递,则testref可以更改原始t引用的内容。也就是说,让它指向一个不同的对象。
用
1 2 3 4 |
方法完成后,将更改t。
把参考类型(如
如果在不使用
将
实际上,引用类型变量不包含"object 8675309"形式的字符串;它们甚至不包含任何可以有意义地转换为数字的内容。尽管每个引用类型变量都将保存一些位模式,但是存储在这些变量中的位模式与它们标识的对象之间没有固定的关系。代码无法从一个对象或对它的引用中提取信息,随后确定另一个引用是否标识了同一个对象,除非代码持有或知道标识原始对象的引用。
这就像在.NET中向指针传递一个指针,这将允许您更改原始T所指的内容,尽管我个人认为,如果您在.NET中这样做,可能会遇到设计问题!
- 呼叫者
- Callee。
通过对引用类型使用
ref表示函数是可以获取对象本身的指针,还是只能获取其值。
传递引用不绑定到语言;它是传递值、传递名称、传递需求等旁边的参数绑定策略。
旁注:在这个上下文中,类名
但是,如果传递的是一个值,则情况会有所不同。可以强制通过引用传递值。例如,这允许您将一个整数传递给一个方法,并让该方法代表您修改该整数。