在Struct中存储引用类型

时间:2012-02-16 15:46:38

标签: c# struct

说我在c#

中有一个非常简单的结构
   public struct foo{
   public  int a{get;set;}
   public  int b{get;set;}
   public  int c{get;set;}
   public  int d{get;set;}
   public  string hello {get;set;}
   }

我认为上面比使用class

更“有效”

在什么时候,如果我继续添加字符串属性,是时候将结构转换为类了吗?

编辑:我原本计划围绕以GDI为中心的应用程序传递此结构。 在处理主要的值类型时,我总是假设结构更高效。

6 个答案:

答案 0 :(得分:26)

  

我认为上面比使用类更“有效”?

绝对不是。 这是一个糟糕的结构。结构应该很小;不超过,例如,参考尺寸的四倍;你的struct是32位机器上五个引用的大小。结构应代表;这似乎不代表任何价值。结构应该是不可变的;这充满了可变性。

  

在什么时候,如果我继续添加字符串属性,是时候将结构转换为类了吗?

将此结构转换为类的重点是您创建它的那一刻。它本来就不应该是一个结构。你的默认假设应该是类足够好;只有当你有证据证明这样做能解决你实际遇到的问题时,才会进入结构。

  

我原计划围绕以GDI为中心的应用程序传递此结构。在处理主要的值类型时,我总是假设结构更高效。

在极少数情况下,结构比类更有效:当它们不可变时,表示,并且由其他值组成,如整数。在其他情况下,它们效率较低:因为结构是按值复制的,所以使用大型结构比引用要慢得多。因为结构是按值复制的,所以可变结构会导致错误,因为当您认为变异变量时,您会复制副本。因为结构是按值复制的,所以它们应该具有值的语义,而不是引用。并且因为垃圾收集器可以完全跳过仅包含其他结构的结构,所以结构只有在没有引用的情况下才能更有效地进行清理。

在任何情况下,您判断某些内容是否更有效的方式是尝试两种方式并根据您的效果目标衡量其效果使用科学。设定目标并进行衡量。使用结构“因为我认为它们更有效”是根据传闻做出技术决定。 衡量,然后您就会知道效率更高。

答案 1 :(得分:4)

如果您需要类提供的增强功能(例如继承),请切换。如果没有,结构可以有点“轻”,但除非你预见到一些性能问题,比如在一个带有大量迭代的紧密循环内的垃圾收集,每当你需要使用ref传递结构想要一个方法来进行修改等可以创造不必要的工作。 (尽管如此,在该示例中,销毁具有引用类型属性的结构也会导致GC)。

实际结果是:是否使用结构或类是您的用例问题,而不是您拥有的属性数。

为了更好地解释类和结构之间的差异和相对的优缺点,see this MSDN article

Eric Lippert关于垃圾收集,结构和类的优秀说明,see his response to this question

答案 2 :(得分:1)

结构具有一些独特的优势,但效率不一定是其中之一。

通常最好使用一个类,除非你真的知道为什么需要一个结构,无论该类型有多少属性。

答案 3 :(得分:1)

我不认为这是一个例子,如果你继续添加字符串,这是你想要对象做什么的情况。结构是值类型,类是引用类型,我理解的结构有一些性能提升(在内存堆/堆栈分配方面),但我认为这取决于你对对象做了什么。

思考我读过一次结构对于短命的很多对象都很好,但我可能是错的。

答案 4 :(得分:0)

如果有人说:

  foo x[100];
  foo[1] = foo[2];
  foo[1].a += 5;

后一个陈述会影响foo[2].a吗?如果foo是结构类型,则不会;如果它是类类型,它会。

与Lippert先生所说的相反,你的类型可能只是一个结构,但有一些注意事项:

  1. 结构应直接暴露其字段,而不是通过属性,除非属性中包含一些非平凡的逻辑。
  2. 传递大于16字节的值结构比传递较小的结构要慢一些,因为.net对较小的结构有特殊处理。但是,通过ref传递不受结构大小的影响。
  3. 包含可变引用类型的可变结构通常表现出语义,这是可变值语义和可变引用语义之间的奇怪交叉。但是,对于保存不可变引用类型(如`string`)的结构,这不是问题。
  4. 结构类型的属性通常很难处理。引用类型的只读属性有时更容易使用,但是替换一个包含20个字节数据的结构类型,同时包含20个字节数据的类,几乎可以使32位系统上的存储要求翻倍,或者在64位系统上超过两倍。

可变值类型语义很有用。较旧的C#编译器(多年前)有一些问题,有些人想阻止人们学习理解它们,但这些并不是在适当的时候不使用它们的好理由。

答案 5 :(得分:-3)

请记住,你在结构中声明的内容是defualt公开的。如果您希望隐藏数据,则必须使用类。除此之外,结构中没有OOP的所有典型功能。

仅供参考:Class (computer programming)