Dictionary.Value随着分配给它的对象的变化而变化

时间:2018-07-20 08:22:42

标签: c# dictionary object

我正在尝试制作(string,WI)的字典,其中WI是我定义的类。

代码如下:

namespace Tracking
{
    class Program
    {
        static public Dictionary<string, WI> Dict = new Dictionary<string, WI>();

        static void Main(string[] args)
        {
            WI oWI = new WI(some_arg);
            string key = "mykey";
            if (!Dict.ContainsKey(key))
            {
                Dict.Add(key, oWI);
            }

            var before = Dict[key];

            oWI = new WI(another_arg);

            var after = Dict[key];
        }
    }
}

问题在于,在更改oWI之后,Dict[key].Value中的所有内容也会更改,即,“ before”和“ after”的值不相同。

它们之间似乎有联系。如何断开连接?字典不应该自己制作WI对象的副本吗?我在做什么错了?

3 个答案:

答案 0 :(得分:2)

TL; DR:使用提供的代码不会显示报告的行为

就像WI所做的那样,“聪明”的事情如果没有WI的定义就无法重新创建。

演示

以下代码输出

Before: One
After: One

即。更改引用oWI不会更改对oWI先前引用的对象的其他引用

using System;
using System.Collections.Generic;

class WI
{
    public string Data { get; private set; }

    public WI(string x)
    {
        Data = x;
    }
}
class Program
{
    static public Dictionary<string, WI> Dict = new Dictionary<string, WI>();
    const string some_arg = "One";
    const string another_arg = "Two";

    static void Main(string[] args)
    {
        WI oWI = new WI(some_arg);
        string key = "mykey";
        if (!Dict.ContainsKey(key))
        {
            Dict.Add(key, oWI);
        }

        var before = Dict[key];
        Console.WriteLine($"Before: {before.Data}");

        oWI = new WI(another_arg);

        var after = Dict[key];
        Console.WriteLine($"After: {after.Data}");
    }
}

答案 1 :(得分:1)

您需要将oWI1对象复制到另一个新对象。如果WI类是引用类型,则需要实现ICloneable接口并进行深克隆。让两个对象指向不同的位置。

例如:

WI实现ICloneable的do Clone方法,它将返回一个新的WI对象。

public class WI : ICloneable
{
    public int age1 { get; set; }
    public object Clone()
    {
        return new WI() { age1 = this.age1 };
    }
}

使用时

var after = Dict[key].Clone() as WI;

答案 2 :(得分:0)

问题在于字典仅保留对创建的对象oWI的引用。因此,如果oWI(字典所指向的)被更改,这也将反映在字典中。

考虑直接在字典中创建对象,以访问与字典隔离的对象。像这样:

string key = "mykey";
if (!Dict.ContainsKey(key))
{
    Dict.Add(key, new WI(some_arg));
}