我有以下示例struct
:
struct Data {
internal long a;
internal long b;
internal void Deconstruct(out long aa, out long bb) {
aa = a; bb = b;
}
}
如果我只想使用struct的值而忘记struct本身怎么办?
Data Generate()
=> new Data() { a = 3, b = 5 };
void Test() {
(var a, var b) = Generate();
Console.WriteLine(a);
Console.WriteLine(b);
}
对Generate
的调用会创建一个结构,并在其各个部分立即进行分解。我可以以某种方式内联这个过程并完全摆脱结构吗?
我在发布模式下使用VS 15.5.7编译(此类库)ilspy显示:
.method private hidebysig
instance void Test () cil managed
{
// Method begins at RVA 0x208c
// Code size 33 (0x21)
.maxstack 3
.locals init (
[0] int64,
[1] valuetype StackOverflowDemo.Q1/Data,
[2] int64,
[3] int64
)
IL_0000: ldarg.0
IL_0001: call instance valuetype StackOverflowDemo.Q1/Data StackOverflowDemo.Q1::Generate()
IL_0006: stloc.1
IL_0007: ldloca.s 1
IL_0009: ldloca.s 2
IL_000b: ldloca.s 3
IL_000d: call instance void StackOverflowDemo.Q1/Data::Deconstruct(int64&, int64&)
IL_0012: ldloc.2
IL_0013: ldloc.3
IL_0014: stloc.0
IL_0015: call void [System.Console]System.Console::WriteLine(int64)
IL_001a: ldloc.0
IL_001b: call void [System.Console]System.Console::WriteLine(int64)
IL_0020: ret
} // end of method Q1::Test
答案 0 :(得分:4)
如果你想忘记结构,而不是
Data Generate()
=> new Data() { a = 3, b = 5 };
为什么不使用
void Generate(out long aa, out long bb)
{
aa = 3; bb = 5;
}
这消除了你提出的结构。
如果你想保留结构但摆脱额外的分配,你也可以这样做:
class Data {
public long A { get; internal set; }
public long B { get; internal set; }
internal Data(long a, long b) {
A = a; B = b;
}
}
然后使用:
void Test() {
var data = Generate();
Console.WriteLine(data.A);
Console.WriteLine(data.B);
}
答案 1 :(得分:0)
根据 mikez 的建议,我使用windbg
和sos
扩展程序查看了jitted代码。
我从中学到了三件事:
感谢您提供所有有用的意见。
如果不对原始源代码进行进一步修改,这就是!Name2EE
方法的Test
输出:
C:\Users\...\source\repos\StackOverflowDemo\Q1.cs @ 37:
>>> 00007ffa`02c41d00 56 push rsi
00007ffa`02c41d01 4883ec30 sub rsp,30h
00007ffa`02c41d05 33c0 xor eax,eax
00007ffa`02c41d07 4889442420 mov qword ptr [rsp+20h],rax
00007ffa`02c41d0c 4889442428 mov qword ptr [rsp+28h],rax
00007ffa`02c41d11 488d542420 lea rdx,[rsp+20h]
00007ffa`02c41d16 e8dde6ffff call 00007ffa`02c403f8 (StackOverflowDemo.Q1.Generate(), mdToken: 0000000006000003)
00007ffa`02c41d1b 488b4c2420 mov rcx,qword ptr [rsp+20h]
00007ffa`02c41d20 488b742428 mov rsi,qword ptr [rsp+28h]
C:\Users\...\source\repos\StackOverflowDemo\Q1.cs @ 38:
00007ffa`02c41d25 e8eee5ffff call 00007ffa`02c40318 (System.Console.WriteLine(Int64), mdToken: 0000000006000080)
C:\Users\...\source\repos\StackOverflowDemo\Q1.cs @ 39:
00007ffa`02c41d2a 488bce mov rcx,rsi
00007ffa`02c41d2d e8e6e5ffff call 00007ffa`02c40318 (System.Console.WriteLine(Int64), mdToken: 0000000006000080)
C:\Users\...\source\repos\StackOverflowDemo\Q1.cs @ 40:
00007ffa`02c41d32 90 nop
00007ffa`02c41d33 4883c430 add rsp,30h
00007ffa`02c41d37 5e pop rsi
00007ffa`02c41d38 c3 ret
对于Generate
方法:
C:\Users\...\source\repos\StackOverflowDemo\Q1.cs @ 28:
>>> 00007ffa`02c41d50 b803000000 mov eax,3
00007ffa`02c41d55 b905000000 mov ecx,5
00007ffa`02c41d5a 488902 mov qword ptr [rdx],rax
00007ffa`02c41d5d 48894a08 mov qword ptr [rdx+8],rcx
00007ffa`02c41d61 488bc2 mov rax,rdx
00007ffa`02c41d64 c3 ret
据我所知,堆栈上没有分配结构。