在这种情况下是否可以避免属性方法调用的开销(以某种方式强制编译器内联?我知道这更像是别名,但 C# 中没有这样的东西):
unsafe public static class Results
{
public static void Test()
{
var cstruct = new CStruct();
var obj = new WrapperForCStruct(&cstruct);
var x = obj.Field;
var y = obj.ptr->field;
}
}
public struct CStruct
{
public int field;
}
unsafe public sealed class WrapperForCStruct(CStruct* pointer)
{
public CStruct* ptr = pointer;
public int Field => ptr->field;
}
与 obj.ptr->field 相比,访问 obj.Field 有开销:
IL(锐实验室)
var x = obj.Field;
IL_0010: dup
IL_0011: callvirt instance int32 WrapperForCStruct::get_Field()
IL_0016: pop
var y = obj.ptr->field;
IL_0017: ldfld valuetype CStruct* WrapperForCStruct::ptr
IL_001c: ldobj CStruct
IL_0021: pop
反汇编(发布-优化)
var x = obj.Field;
00007FFDB5C43E96 mov rcx,qword ptr [rbp-10h]
00007FFDB5C43E9A cmp dword ptr [rcx],ecx
00007FFDB5C43E9C call qword ptr [CLRStub[MethodDescPrestub]@00007FFDB5E4D5F0 (07FFDB5E4D5F0h)]
00007FFDB5C43EA2 mov dword ptr [rbp-14h],eax
00007FFDB5C43EA5 nop
var y = obj.ptr->field;
00007FFDB4223E97 mov rcx,qword ptr [rbp-10h]
00007FFDB4223E9B mov rcx,qword ptr [rcx+8]
00007FFDB4223E9F cmp byte ptr [rcx],cl
在这种情况下,我实际上会执行托管指针,并将 WrapperForCStruct 设置为
ref struct
。这样我们就可以拥有 ref field
而不是属性。有了满口的 readonly
修饰符,我们就有了一个“吸气剂”。
struct CStruct {
public int field;
}
ref struct WrapperForCStruct {
public readonly ref readonly int Field;
public WrapperForCStruct(ref CStruct cstruct) {
Field = ref cstruct.field;
}
}