C#字典值引用类型 - 请解释为什么会发生这种情况

use*_*444 2 c# dictionary pass-by-reference

我不理解C#中以下linqpad查询的结果.评论应该解释我感到困惑的地方.

void Main()
{
    Dictionary<string, testClass> test = new Dictionary<string, testClass>();

    string key = "key";
    testClass val = null;

    test.Add(key, val);

    val = new testClass();

    test[key].Dump(); //returns null.   WHAT? I just set it!!!



    test[key] = val;
    val.Text = "something";
    //  returns val object, with Text set to "Something". 
    //  If the above didn't work, why does this work?
    test[key].Dump(); 



    val.Text = "Nothing";
    //  return val object, with Text set to "Nothing". 
    //  This, I expect, but, again, why didn't the first example work?
    test[key].Dump(); 



    val = null;
    //  returns val object, with Text set to "Nothing"...WHAT?? 
    //  Now my head is going to explode...
    test[key].Dump(); 

}

// Define other methods and classes here

public class testClass
{
    public override string ToString()
    {
        return Text;
    }

    public string Text { get; set;}     
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*way 6

主要原因是变量(val)不是对象.它只包含对象的引用(或null).

testClass val = null声明一个类型的变量testClass并将其设置为null.它没有指向任何对象.

test.Add(key, val)在添加指向空的词典中的条目(注:它指向val也不指向任何对象).

val = new testClass();创建一个的实例testClassval现在指向新的对象. test[key] 仍为null并且不指向任何对象.

test[key] = val;
val.Text = "something";
test[key].Dump(); 
Run Code Online (Sandbox Code Playgroud)

此代码指向test[key]指向的同一对象val.再说一遍,它没有指向val.当您更改对象时,val.Text = "something"您可以看到使用的更改,test[key].Dump()因为它们都指向同一个对象.

val.Text = "Nothing";
test[key].Dump(); 
Run Code Online (Sandbox Code Playgroud)

当您设置val.Text为字符串"Nothing"时,您可以看到更改test[key],原因与上面相同,它们都指向同一个对象.

val = null;
test[key].Dump(); 
Run Code Online (Sandbox Code Playgroud)

此代码设置val为null. test[key] 仍然指向对象.现在val,test[key]指出不同的事情.


Jon*_*lis 5

test.Add(key, val);
val = new testClass();
test[key].Dump(); //returns null.   WHAT? I just set it!!!
Run Code Online (Sandbox Code Playgroud)

你正在重新实例化val.它不再指向您添加到的同一对象test.当您新建一个参考对象时,它指向一个全新的对象.


比方说,如果您有int房产testClass并且做了:

var c = new testClass{ MyProperty = 1}
test.Add(key, c);

c.MyProperty = 2;
test[key].MyProperty.Dump();
Run Code Online (Sandbox Code Playgroud)

看到2输出,因为你没有改变c指向的对象,但改变了现有对象的属性.

  • @EdPlunkett在此上下文中重新实例化意味着再次实例化.没有什么不同于实例化. (3认同)