访问结构体字段复制整个结构体
本文关键字:结构体 字段 访问 复制 | 更新日期: 2023-09-27 18:04:05
我知道将结构体作为参数传递给方法,返回它们,或者尝试将结构体值赋给变量会创建整个结构体的副本。
现在,看看下面的假设代码://Regions is an array of a struct type. Color and r/g/b are structs too.
if(Regions[0].Color.r == Regions[0].Color.g && Regions[0].Color.b != 0){
.
..
}
要得到r/g/b值,下面发生了什么?只有r/g/b值被复制到内存位置或整个区域[0]三次?
我认为这段代码复制了你的问题:
void Main()
{
var foos = new Foo[]
{
new Foo() { Color = System.Drawing.Color.Red },
};
if (foos[0].Color.R == 45 && foos[0].Color.B == 55)
{
Console.WriteLine("!");
}
}
public struct Foo
{
public System.Drawing.Color Color;
}
产生的IL是:
<>之前IL_0000: ldc.i4.1[00:01 . 00] [qhIL_0006: dupIL_0007: ldc.i4.0IL_0008: ldloca。年代01IL_000A: initobj FooIL_0010: ldloca。年代01IL_0012:调用System.Drawing.Color.get_RedIL_0017: stfld Foo。颜色IL_001C: ldloc.1IL_001D: stelem FooIL_0022: stloc。0//fooIL_0023: ldloc。0//fooIL_0024: ldc.i4.0IL_0025: ldelema Foo[au:] [au:]颜色IL_002F:调用System.Drawing.Color.get_RIL_0034: ldc.i4。年代2 dIL_0036: bne.un.s IL_0057IL_0038: ldloc。0//fooIL_0039: ldc.i4.0IL_003A: ldelema Foo[au:] [au:]颜色IL_0044:调用System.Drawing.Color.get_BIL_0049: ldc.i4。年代37IL_004B: bne.un.s IL_0057IL_004D: "!"IL_0052:调用System.Console.WriteLineIL_0057:受潮湿腐烂之前您将注意到ldelema
和ldflda
各有两批op码。两者都只是传递引用。
所以,不需要复制两个副本。
Region是一个结构体数组。我做了一个快速示例来检查生成的IL:
public class Program
{
public static void Main()
{
Foo[] Regions = new Foo[10];
Regions[0] = new Foo();
if(Regions[0].Color.R == Regions[0].Color.G && Regions[0].Color.B != 0)
{
}
}
}
public struct Foo
{
public Color Color { set; get; }
}
正如您在下面生成的IL中看到的那样,get_Color
被调用了3次,因此Color的值被复制了3次并被检索。
.method public hidebysig static void Main() cil managed
{
//
.maxstack 3
.locals init (valuetype Foo[] V_0,
valuetype [System.Drawing]System.Drawing.Color V_1,
bool V_2)
IL_0000: nop
IL_0001: ldc.i4.s 10
IL_0003: newarr Foo
IL_0008: stloc.0
IL_0009: ldloc.0
IL_000a: ldc.i4.0
IL_000b: ldelema Foo
IL_0010: initobj Foo
IL_0016: ldloc.0
IL_0017: ldc.i4.0
IL_0018: ldelema Foo
IL_001d: call instance valuetype [System.Drawing]System.Drawing.Color Foo::get_Color()
IL_0022: stloc.1
IL_0023: ldloca.s V_1
IL_0025: call instance uint8 [System.Drawing]System.Drawing.Color::get_R()
IL_002a: ldloc.0
IL_002b: ldc.i4.0
IL_002c: ldelema Foo
IL_0031: call instance valuetype [System.Drawing]System.Drawing.Color Foo::get_Color()
IL_0036: stloc.1
IL_0037: ldloca.s V_1
IL_0039: call instance uint8 [System.Drawing]System.Drawing.Color::get_G()
IL_003e: bne.un.s IL_0059
IL_0040: ldloc.0
IL_0041: ldc.i4.0
IL_0042: ldelema Foo
IL_0047: call instance valuetype [System.Drawing]System.Drawing.Color Foo::get_Color()
IL_004c: stloc.1
IL_004d: ldloca.s V_1
IL_004f: call instance uint8 [System.Drawing]System.Drawing.Color::get_B()
IL_0054: ldc.i4.0
IL_0055: ceq
IL_0057: br.s IL_005a
IL_0059: ldc.i4.1
IL_005a: nop
IL_005b: stloc.2
IL_005c: ldloc.2
IL_005d: brtrue.s IL_0061
IL_005f: nop
IL_0060: nop
IL_0061: ret
} // end of method Program::Main