2015-06-14 85 views
0

我想如果我可以做一个引用,总是指向该特定变量,而不是指向该变量当前表示的对象(或更准确地说是内存位置)。参考变量,而不是对象

举一个例子,假设我有以下程序,我想创建一个对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#做到这一点,或者任何可以防止被分配给一个新的存储位置的变量(以使上面的代码将在返回错误= b)的?

+1

,你可以将它定义为只读 – dotctor

+0

做你试着做StoreReference(REF MyClass的输入) –

+0

用只读的问题是,我希望能够说a.value中= 42而不是=新MyClass的()因为第二个示例更改了指向的内存位置。 – user3875080

回答

0

您可以检查是否saved已经有值与否:

static void StoreReference(MyClass input) 
{ 
    if (saved != null) { 
     return; 
    } 
    saved = input; 
} 
0

我在这里看到了不少回应是建议使用一个readonly场或ref参数,但我不知道我完全理解为什么这些相关。所以请原谅我,如果我不明白你的问题。

但是从我看到的情况来看,您希望否定作业的效果(a = b;),这是不可能的。

唯一的选择是切换到您的通话使用saved代替aConsole.Write

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:这是一个完全合理的修改,把你的场,它:

  1. 只适用于字段,这意味着它将保护saved但不是局部变量。
  2. 只允许在构造函数中设置值,而不是您要在此处设置的值。

所以,如果你打算使用它,不要误解我的意思,它对于它做的事很好,请谨慎对待这两个事实。你需要重新设计。说实话,我会避免在static void Main(...) - 无论如何构造器废话可能会让人困惑。

无论如何,我认为你可能会试图解决一个本来不应该存在的问题。这可能有助于看到一个真实世界的用例,但是从您给我们的看法来看,这听起来不像是可能的事情,不幸的是有充分的理由。


对于它的价值,你的标题和开头段让我觉得你正在寻找一个指针的指针,这是不是在管理C#允许的。我从来没有冒险进入非托管C#,但它允许在C++中,所以我怀疑它可能在那里支持。无论如何,你的问题的其余部分并没有真正提醒我,所以这可能不相关。