【发布时间】:2011-02-07 10:02:25
【问题描述】:
假设我有一个Person 类并且有以下内容:
Person A = new Person("Tom");
Person B = A;
有没有办法可以改变它,这样如果我将一个新的Person 分配给B、B = new Person("Harry")、A 也会指同一个实例?我知道你可以在函数的 ref 参数分配中做到这一点。
【问题讨论】:
假设我有一个Person 类并且有以下内容:
Person A = new Person("Tom");
Person B = A;
有没有办法可以改变它,这样如果我将一个新的Person 分配给B、B = new Person("Harry")、A 也会指同一个实例?我知道你可以在函数的 ref 参数分配中做到这一点。
【问题讨论】:
更新:此处描述的功能已添加到 C# 7。
您想要的功能称为“ref locals”,它在 C# 中不受支持。
CLR 确实支持生成包含 ref locals 的代码,并且几年前我编写了一个具有您想要的功能的 C# 的实验版本,只是为了看看它是否可以工作。你可以这样做:
Person a = whatever;
ref Person b = ref a;
然后正如您所说,对“b”的更改会更改“a”的内容。这两个变量成为同一个存储位置的别名。
虽然这是一个不错的小功能并且运行良好,但我们决定不将它用于 C#。有可能它仍然会发生在该语言的假设未来版本中,但我不会对此感到兴奋。它可能不会发生。
(请记住,Eric 对任何 Microsoft 产品的假设未来版本的所有想法均仅用于娱乐目的。)
【讨论】:
不,这在安全代码中是不可能的(除了ref 函数参数)。在不安全的代码中,您也许可以使用指针来实现这一点,但我认为这不是一个好主意。
A 包含对“Tom”的引用作为值。您需要引用 A 来更改它指向的位置。
如果我们考虑一种语言中的类似代码,它显式使用指针而不是将类的实例隐式视为引用:
Person* A=new Person("Tom");
Person* B=A;
B=new Person("Harry");//Changes only B
Person** C=&A;
(*C)=new Person("John");//Now A changes
所以你需要一个指向指针的指针才能改变A。如果将其传输到 C#,则需要对局部变量的引用。而这些仅以ref 函数参数的形式提供。这避免了一些生命周期问题,因为对局部变量的引用不能安全地超过该局部变量。
如果这些不是私有变量,您可以使 B 成为在 setter 中修改 A 的属性。
Person B{get{return A;} set{A=value;}}
【讨论】:
Person 声明为类,则其类型的变量将被隐式视为指针/引用。
没有直接的方法可以做到这一点。
您可以采用源代码方法,例如:
A = B = new Person("Harry")
或者使用泛型类型。比如:
var A = new ReferenceHolder<Person> (new Person("Tom"));
var B = A;
在 C# 中,您也可以使用指针(基本上是 ref 类型),但这种方法不是静态可验证的,也不建议使用。
【讨论】: