当我进行以下基准测试时,基准信息表明没有额外的内存分配。但是,将结构体转换为接口不涉及装箱吗?
[MemoryDiagnoser]
public class Test
{
[Benchmark]
public Color Test123()
{
Color color = new Color();
IFormattable formattable = color;
return (Color)formattable;
}
[Benchmark]
public int Test234()
{
int number = 114514;
IConvertible convertible = number;
return (int)convertible;
}
}
[StructLayout(LayoutKind.Sequential)]
public struct Color : IFormattable
{
public double R { get; set; }
public double G { get; set; }
public double B { get; set; }
public double A { get; set; }
public static Color GetRandomColor()
{
Random rand = new Random();
double r = rand.Next(0, 256) * rand.NextDouble();
double g = rand.Next(0, 256) * rand.NextDouble();
double b = rand.Next(0, 256) * rand.NextDouble();
double a = rand.Next(0, 256) * rand.NextDouble();
return new Color(r, g, b, a);
}
public string ToString(string? format, IFormatProvider? formatProvider)
{
return $"{R} {G} {B} {A}";
}
public Color(double r, double g, double b, double a)
{
R = r;
G = g;
B = b;
A = a;
}
public static bool operator ==(Color left, Color right)
{
return left.R == right.R && left.G == right.G && left.B == right.B && left.A == right.A;
}
public static bool operator !=(Color left, Color right)
{
return !(left == right);
}
}
.NET 8
Color 结构仅包含四个双成员:RGBA。
“我尝试打开Rider分析IL代码,发现确实有装箱和拆箱指令。我想了解为什么没有额外的内存分配。”
.method public hidebysig static valuetype Program.Color
Test123() cil managed
{
.maxstack 1
.locals init (
[0] valuetype Program.Color color,
[1] class [System.Runtime]System.IFormattable formattable,
[2] valuetype Program.Color V_2
)
// [28 9 - 28 10]
IL_0000: nop
// [29 13 - 29 39]
IL_0001: ldloca.s color
IL_0003: initobj Program.Color
// [30 13 - 30 46]
IL_0009: ldloc.0 // color
IL_000a: box Program.Color
IL_000f: stloc.1 // formattable
// [31 13 - 31 39]
IL_0010: ldloc.1 // formattable
IL_0011: unbox.any Program.Color
IL_0016: stloc.2 // V_2
IL_0017: br.s IL_0019
// [32 9 - 32 10]
IL_0019: ldloc.2 // V_2
IL_001a: ret
} // end of method Program::Test123
JIT 编译器足够智能,可以删除
formattable
体操,并且本质上只返回 color
如果您更改方法以实际返回 IFormattable,您将获得分配:
public IFormattable Test123() {
Color color = new Color();
IFormattable formattable = color;
return formattable;
}