引用变量,而不是对象
本文关键字:对象 变量 引用 | 更新日期: 2023-09-27 17:56:15
我希望我可以做一个引用,该引用将始终指向该特定变量,而不是指向该变量当前表示的对象(或更准确地说是内存位置)。
例如,假设我有以下程序,我想创建一个对 MyClass a 的引用,以便它始终返回 MyClass a 中的任何值,即使该值发生变化。我有一些看起来像的代码。
class MyClass
{
public int value = 0;
}
class Program
{
static MyClass saved; //maintained and used by the following two functions
static void StoreReference(MyClass input)
{
saved = input;
}
static void SetValue()
{
saved.value = 42;
}
static void Main(string[] args)
{
//A couple arbitrary classes I'd like to have references to
MyClass a = new MyClass();
MyClass b = new MyClass();
StoreReference(a);
a = b;
SetValue();
Console.Write(a.value); //should print 42, instead prints 0 since it reads in the original object a was set to
}
}
是否有任何可以在 C# 中执行此操作,或者是否有任何可以阻止变量分配给新内存位置的东西(以便上面的代码将在 a = b 处返回错误)?
您可以检查saved
是否已经具有值:
static void StoreReference(MyClass input)
{
if (saved != null) {
return;
}
saved = input;
}
我在这里看到很多建议使用readonly
字段或ref
参数的响应,但我不确定我是否完全理解为什么这些是相关的。因此,如果我不明白您的问题,请原谅我。
但从我所看到的,你想否定赋值的效果(a = b;
),这是不可能的。
唯一的选择是在调用Console.Write
时切换到使用 saved
而不是a
static void Main(string[] args)
{
MyClass a = new MyClass();
MyClass b = new MyClass();
StoreReference(a);
a = b;
SetValue();
Console.Write(saved.value);
}
这将起作用,它将像您想要的那样打印 42。但我明白这不是你要找的。
但是,没有任何语言功能可以让代码编译并让您做您想做的事情。这是一件好事。这就是编译器运行这些检查(或部分检查)的原因。如果你忘记了你有一个虚构的修饰符来使局部变量只读,并且你写出了赋值,期望它像任何C语言中的其他地方一样工作,那将是非常令人困惑的。
现在,关于其他人一直在说的话,我真的不确定我明白为什么ref
会出现,但是readonly
:这是一个完全合理的修饰符,可以放在你的领域,但它:
- 仅适用于字段,这意味着它将保护
saved
但不能保护局部变量。 - 仅允许在构造函数中设置值,这不是您在此处尝试设置值的位置。
因此,如果您确实打算使用它,并且不要误会我的意思,它对它的作用非常有用,请警惕这两个事实。您需要重新构建一些架构。老实说,无论如何,我都会在static void Main(...)
中避免这种情况 - 那里的构造函数废话可能会令人困惑。
无论如何,我认为您可能正在尝试解决一个本来就不应该存在的问题。看到一个真实的用例可能会有所帮助,但从你给我们的信息来看,这听起来不像是可能的,不幸的是,这是有充分理由的。
值得一提的是,您的标题和开头段落让我认为您正在寻找指向指针的指针,这在托管 C# 中是不允许的。我从未涉足过非托管 C#,但它在C++中是允许的,所以我怀疑它可能在那里得到支持。无论如何,你问题的其余部分并没有真正提醒我这一点,所以这可能无关紧要。