当您将值类型的实例分配给另一个实例时,该对象将逐位复制到目标位置:
private struct Word
{
public Word(char c) { ... }
}
public void Method(Word a)
{
Word b = a; //a is copied and stored in b
}
但是给出了以下代码:
private Word _word;
public void Method() {
_word = new Word('x');
}
我怀疑首先评估右侧(RHS)表达式 - 它实例化堆栈上的值类型 - 然后然后将值复制并存储在{{的位置上1}}字段,位于堆上。
另一种方法是考虑左侧,并直接在_word
上实例化值类型,避免复制对象。
我的怀疑是否正确?如果是,我想可以安全地假设第一个代码块比第二个代码块表现更好。
_word
注意:我不打算对任何事情进行微观优化。
编辑:我的问题的核心是,正如李所说:结构是直接分配到的,还是需要分配然后复制?
答案 0 :(得分:9)
当您将值类型的实例分配给另一个实例时,该对象将逐位复制到目标位置
将值类型的实例分配给相同类型的变量时,该值将复制到目标位置,是。但对于引用类型也是如此:引用被逐位复制到目标位置。 指示物当然保持在原地。
我怀疑首先评估右侧(RHS)表达式
规范声明左侧被评估以产生变量,然后评估右侧产生一个值,然后进行赋值。
在示例中,您给左侧的评估不会产生可观察到的副作用,因此它的评估可以由C#编译器中的优化器,抖动或CPU重新排序,如果其中任何一个选择的话。但如果你有像
这样的东西x[i++] = v();
然后左手边的副作用必须在右手边的呼叫之前发生。
我的问题的核心是:结构是直接分配的,还是需要分配然后复制?
规范声明结构分配在临时位置 - 通常是堆栈或实际中的寄存器 - 然后复制到它们的最终目的地。然而,在某些情况下,优化器可以确定用户不可能注意到突变是否在最终目的地“就地”发生。这是 copy elision 优化,如果C#编译器感觉它可以逃脱它,它将执行此优化。
有关详细信息,请参阅我关于此主题的文章:
http://ericlippert.com/2010/10/11/debunking-another-myth-about-value-types/
答案 1 :(得分:0)
是首选吗?
多个相同结构的商业案例是什么?
如果你需要多个相同的对象,那么结构是最好的选择吗?
以这种方式初始化的struct(re)可能不是示例用例的良好解决方案 在新阵列中,使用默认ctor(无ctor)分配和初始化WordStruct 您没有选择使用另一个ctor初始化结构数组 如果你确实需要相同的结构,那么这将是首选
WordStruct[] WordStructS = new WordStruct[1000];
for (int i = 0; i < WordStructS.Length; i++) { WordStructS[i].C = 'x'; }
如果你真正需要做多个相同的对象,那么考虑一个班级 分配了一个新的数组,但尚未初始化 您不会浪费使用默认构造函数初始化的资源
WordClass[] WordClassS = new WordClass[1000];
for (int i = 0; i < WordClassS.Length; i++) { WordClassS[i] = new WordClass('x'); }
如果要概括对象(结构或类)的深层副本,请考虑IConable
在结构的情况下,我怀疑它比有点明智的副本更有效(但我不是正面的)
在类的情况下,它将使克隆(深拷贝)而不是参考
public struct WordStruct : ICloneable
{
public char C;
public WordStruct(char C)
{
this.C = C;
}
public object Clone()
{
WordStruct newWordStruct = (WordStruct)this.MemberwiseClone();
return newWordStruct;
}
}
我在评论中说你好奇,但在问题中不明确 在问题中,您说第一个代码块优先于第二个代码
我知道这是一个有趣的好奇心问题 但如果仅仅是好奇心,那么这个问题就应该停止了 我的怀疑是否正确?