结构与课程

Mic*_*hel 89 c# struct

我即将在代码中创建100,000个对象.它们很小,只有2或3个属性.我将它们放在一个通用列表中,当它们存在时,我将循环它们并检查值a并可能更新值b.

将这些对象创建为类还是结构更快/更好?

编辑

一个.属性是值类型(我认为字符串除外?)

湾 他们可能(我们还不确定)有一个验证方法

编辑2

我想知道:堆上的对象和堆栈是否由垃圾收集器同等处理,或者它的工作方式有何不同?

Eri*_*ert 130

难道更快创建这些对象的类或结构?

您是唯一可以确定该问题答案的人.尝试两种方式,衡量有意义的,以用户为中心的相关性能指标,然后您将了解更改是否对相关方案中的真实用户产生了有意义的影响.

结构消耗更少的堆内存(因为它们更小且更容易压缩,而不是因为它们"在堆栈中").但是他们需要比参考副本更长的时间来复制.我不知道您的内存使用或速度的性能指标; 这里有一个权衡,你就是知道它是什么的人.

它是更好的创建这些对象的类或结构?

也许是阶级,也许是结构.根据经验:如果对象是:
1.小
2.逻辑上是不可变的值
3.有很多它们
然后我会考虑把它变成一个结构.否则我会坚持使用引用类型.

如果你需要改变一个struct的某个字段,通常最好构建一个构造函数,该构造函数返回一个正确设置字段的整个新结构.这可能稍微慢一些(测量它!)但在逻辑上更容易推理.

垃圾收集器是否同样处理堆和堆栈上的对象?

,它们不一样,因为堆栈上的对象是集合的根.垃圾收集器不需要问"堆栈中的这个东西是活着的吗?" 因为这个问题的答案总是"是的,它在堆栈上".(现在,你不能靠,要保持一个对象活着,因为堆栈的实现细节.抖动允许引进的优化,比如说,enregister什么通常会是一个堆栈值,然后它永远不会在堆栈上所以GC不知道它仍然活着.一个enregistered对象可以收集及其后代积极,只要登记持有到它不会再次被读取.)

但垃圾收集器确实必须将堆栈上的对象视为活动,就像它将任何已知的活动对象视为活着一样.堆栈上的对象可以引用需要保持活动的堆分配对象,因此GC必须将堆栈对象视为活动堆分配对象,以便确定实时集.但显然它们不是为了压缩堆被视为"活动对象",因为它们首先不在堆上.

明白了吗?


ja7*_*a72 22

有时struct您不需要调用new()构造函数,并直接分配字段,使其比平时快得多.

例:

Value[] list = new Value[N];
for (int i = 0; i < N; i++)
{
    list[i].id = i;
    list[i].is_valid = true;
}
Run Code Online (Sandbox Code Playgroud)

大约快2到3倍

Value[] list = new Value[N];
for (int i = 0; i < N; i++)
{
    list[i] = new Value(i, true);
}
Run Code Online (Sandbox Code Playgroud)

哪里Valuestruct两个字段(id和is_valid).

另一方面,需要移动项目或选择值类型所有复制将减慢你的速度.为了得到确切的答案,我怀疑你必须分析你的代码并测试它.


kyn*_*igs 7

结构可能看起来类似于类,但是您应该注意一些重要的区别.首先,类是引用类型,结构是值类型.通过使用结构,您可以创建行为类似于内置类型的对象,并享受它们的好处.

在类上调用New运算符时,它将在堆上分配.但是,当您实例化一个结构时,它会在堆栈上创建.这将带来性能提升.此外,您将不会像处理类那样处理对结构实例的引用.您将直接使用struct实例.因此,在将结构传递给方法时,它是通过值而不是作为引用传递的.

更多信息:

http://msdn.microsoft.com/en-us/library/aa288471(VS.71).aspx

  • 那篇文章在几个关键点上有误导性,我已经要求MSDN团队修改或删除它. (10认同)
  • 我知道它在MSDN上说它,但MSDN并不是在讲述整个故事.堆栈与堆是一个实现细节,结构不总是*在堆栈上.有关此问题的最新博客,请参阅:http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx (4认同)
  • @supercat:解决你的第一点:更大的一点是在托管代码*中,存储值的值或引用在很大程度上是无关紧要的*.我们一直在努力创建一个内存模型,大多数时候,开发人员允许运行时代表他们做出智能存储决策.当不理解它们时,这些区别非常重要,因为它在C中会产生崩溃的后果; 在C#中没有那么多. (2认同)

Pau*_*ane 6

结构数组在连续的内存块中表示在堆上,而对象数组表示为连续的引用块,实际对象本身位于堆的其他位置,因此需要内存用于对象及其数组引用.

在这种情况下,当您将它们放置在List<>(并且List<>支持到数组中)时,使用结构将在内存方面更有效.

(请注意,大型数组会在大对象堆上找到它们的方式,如果它们的生命周期很长,可能会对进程的内存管理产生负面影响.还要记住,内存不是唯一的考虑因素.)