据我所知,使用结构值类型总是会比使用数组或列表中的引用类型提供更好的性能。在通用列表中使用struct而不是类类型是否有任何缺点?
PS:我知道MSDN建议struct最多16个字节,但到目前为止我一直使用100+字节结构而没有问题。此外,当我因使用结构而超出最大堆栈内存错误时,如果我使用类,我也会用完堆空间。
答案 0 :(得分:4)
关于.Net中的结构与引用类型有很多错误的信息。任何使“结构总是在......中表现更好”的一揽子陈述几乎肯定是错误的。几乎不可能对性能做出全面的陈述。
以下是与通用集合中的值类型相关的几个项目,它们将影响性能。
答案 1 :(得分:2)
正如其他人所指出的那样,在列表中使用大型结构有许多缺点。其他人所说的一些后果:
假设您正在排序其成员为100多字节结构的列表。每次必须交换项目时,都会发生以下情况:
var temp = list[i];
list[i] = list[j];
list[j] = temp;
复制的数据量为3*sizeof(your_struct)
。如果要对由引用类型组成的列表进行排序,则复制的数据量为3*sizeof(IntPtr)
:32位运行时为12个字节,64位运行时为24个字节。我可以从经验告诉你,复制大型结构比使用引用类型固有的间接要昂贵得多。
使用结构还可以减少列表中可以包含的最大项目数。在.NET中,任何单个数据结构的最大大小为2千兆字节(减去一点点)。结构列表的最大容量为2^31/sizeof(your_struct)
。因此,如果您的结构大小为100字节,那么列表中最多可以包含大约2150万个结构。但是,如果使用引用类型,则32位运行时的最大值大约为5.36亿(尽管在达到该限制之前内存不足),或者64位运行时中的2.68亿。而且,是的,我们中的一些人确实在内存中处理了很多事情。
答案 2 :(得分:1)
使用结构值类型总是会比使用数组或列表中的引用类型提供更好的性能
声明中没有任何内容。
答案 3 :(得分:1)
答案 4 :(得分:1)
使用结构体,您不能以类继承的形式重用代码。结构只能实现接口,但不能从类或其他结构继承,而类可以从其他类继承,当然也可以实现接口。
答案 5 :(得分:0)
当在List<T>
或其他集合中存储数据(而不是保留控件或其他活动对象的列表)并希望允许数据更改时,通常应遵循以下四种模式之一:< / p>
方法#1是最简单的,如果想要存储的对象是不可变的。当然,对象不可变的要求可能有些限制。
方法#2在某些情况下可能很方便,并且它允许方便地更新列表中的数据(例如MyList[index].SomeProperty += 5;
)但是返回属性如何附加到列表中的项目的确切语义有时可能不清楚。此外,没有明确的方法从“示例”对象加载列表中项目的所有属性。
方法#3具有易于理解的语义(在将对象提供给列表后更改对象将不起作用,从列表中检索的对象不会受到对列表的后续更改的影响,以及对从中检索的对象的更改除非明确写回对象,否则列表不会影响列表本身,但需要对每个列表访问进行防御性复制,这可能相当麻烦。
方法#4提供与方法#3基本相同的语义,但复制结构比制作类对象的防御副本便宜。请注意,如果结构是可变的,则语义为:
var temp = MyList[index]; temp.SomeField += 5; MyList[index] temp;
比通过所谓的“不可变”(即仅由突变分配)结构可以实现的任何事物更清楚。要知道上面做了什么,所有人都需要知道结构是SomeField
是某种特定类型的公共字段。相比之下,即使是:
var temp = MyList[index]; temp = temp.WithSomeField(temp.SomeField + 5); MyList[index] temp;对于这样的结构来说,这是最好的人所希望的,比易于变构的结构版本更难阅读。此外,为了确保上面的实际操作,我们必须检查结构的
WithSomeField
方法的定义以及由此使用的任何构造函数或方法,以及所有结构的字段,以确定它是否具有除了修改SomeField
之外的任何副作用。