我应该使用struct而不是class来将项目放入字典中

时间:2014-06-10 17:07:47

标签: c# class dictionary struct value-type

我是一个自定义实体类(请参阅下面的代码)。此类的对象将填充到Dictionary集合Dictionary<string, Dictionary <uint,Entity>> dt中。有人要求我使用Struct而不是Class,因为值类型不会被复制到堆中。好吧,我认为在这种情况下Class似乎是更好的选择,因为Dictionary只会包含对Entity类型对象的引用。在这种情况下,实体类型表示csv文件中的一行。因此,对于每一行,都会有一个实体类型对象。实体类型中的封装字典包含表示列的键值,值对,csv文件中行的值。

但是我想确保我没有错过任何明显的事情,所以想要更好地问。

 public class Entity
    {
        Dictionary<string, string> dtValues = new Dictionary<string,string>(); //contains values    from CSV file.
        public Dictionary<string, string> Values
        {
          get { return dtValues; }
          set { dtValues = value; }
        }

    }

3 个答案:

答案 0 :(得分:1)

  

有人要求我使用Struct而不是Class,因为值类型不会被复制到堆中。

那个人是错的。简单地说:字典本身就在堆上,所以它的内容也会在堆上。

如果您不确定是应该使用引用类型还是值类型,那么您应该研究两者的优缺点(我列出了一些here)。但你应该可能使用引用类型。

记住:过早优化是万恶之源。

答案 1 :(得分:1)

使用Structs字典总是一个非常糟糕的主意,因为当你枚举它或对它的值做任何事情时,你会反复复制数据,所以使用类是正确的方法,这样只会移动引用

答案 2 :(得分:0)

为了封装状态而保存对可变对象的引用的类型通常应该避免将这些对象暴露给外部代码。我不太明白你的Entity类型的目的是什么,因为唯一明显的内容是对Dictionary的引用[当然,这是一种可变类型]。

一般来说,如果一个人希望将东西存储在一个集合中并试图决定使用一个类或一个结构来存储的东西,我建议如下:

  1. 如果对列表项或字典 [not keys]使用可变类类型,则可以编辑存储在项目中的信息,而不必将集合本身​​包含在该过程中。但是,将项目中包含的信息提供给外部代码可能需要克隆数据项或将数据从中复制到其他项目中。

  2. 如果对集合中存储的内容使用不可变类类型或任何结构类型,则编辑项目中包含的信息将需要读取项目,生成更改的版本并将其存储回来。但是,将项目中包含的信息提供给外部代码会更容易,因为可以将其作为自己的数据类型返回。

  3. 有时有用的模式是定义一个可变的结构类型,然后定义一个类似下面的包装类型:

    public class ExposedFieldHolder<T>
    {
      public T Value;
      ExposedFieldHolder(T value) { Value = value; }
    }
    
  4. 如果Value是字段,而不是属性,则可以创建例如一个Dictionary<string, ExposedFieldHolder<someStruct>>,那么当数据存储在字典e.g. myDict [“George”]中时,就可以编辑数据.Value.Age ++; but it will also be possible to give the data associated with an entry to outside code [e.g.返回myDict [name] .Value; `]。

    将一个简单的暴露字段结构封装在ExposedFieldHolder<T>中比使用可变类更安全,更方便(因为可以返回持有者的整个Value,而无需外部代码访问持有者本身),并且比使用不可变类或结构更方便(因为可以修改列表项或字典值而无需使用读出 - 修改 - 写回序列)。与简单地将暴露场结构直接存储在集合中相比,它的空间效率较低。如果将一个exposed-field结构直接存储为字典值而不使用`ExposedFieldHolder,那么对George年龄的上述更新将需要三个步骤:

    var temp = myDict["George"];
    temp.Age++;
    myDict["George"] = temp;
    

    但这可能仍然比不可变类或所谓的“不可变”结构需要的更好,例如

    var temp = myDict["George"];
    temp = new PersonDat(temp.Name, temp.Age+1, temp.FavoriteColor, temp.AstrologicalSign);
    myDict["George"] = temp;
    

    请注意,如果在使用公开字段结构时始终遵循前一个模式,则无论结构包含哪些字段或属性或它们出现的顺序,代码都是正确的。相反,当使用后一种模式时,必须非常小心,以确保任何不应更改其值的字段或属性以正确的顺序传递给构造函数。有些人可能喜欢那种代码;我认为这太可怕了。

相关问题