如何用无效的引用语法重构这个反编译的 C# 代码?

How to refactor this decompiled C# code with invalid reference syntax?

反编译一个程序集,生成的代码有很多类似这样的方法:

internal long m_position;

internal void PutString(long RecordNumber, string s)
{
    if (s == null)
        s = "";
    int byteCount = this.m_Encoding.GetByteCount(s);
    this.SetRecord(RecordNumber);
    this.LengthCheck(byteCount);
    if (byteCount != 0)
        this.m_sw.Write(s);
    // ISSUE: variable of a reference type
    long& local;
    // ISSUE: explicit reference operation
    long num = checked (^(local = ref this.m_position) + (long) byteCount);
    local = num;
}

只有从 // ISSUE 开始的代码有问题。如您所见,它包含无效语法 long& local;。我发现 this answer 很好地解释了这是什么。在阅读 C# ref locals 之后,我尝试重构此方法以便它可以编译,但我没有成功。 ^(local = ref this.m_position) 部分真的让我受益匪浅,因为我在按位运算方面不是很强。

有人可以帮我重构最后三行并向我解释它是如何工作的吗?这种模式在反编译代码中几乎一字不差地出现了数百次,所以一旦我“理解”了这个例子,我对其余部分应该没有问题。

long& 表示 long 的引用类型,应替换为 ref long。然后将 m_position 字段的地址分配给 local 变量(使 local 成为它的别名),然后在向其添加字节数时检查算术溢出。不完全确定插入符号,在托管 C++ 中,它是一个 hat 来指示对象的 GC,所以我想这就是它正在做的事情。当算术检查成功完成时,m_position 字段通过 local var 设置为当前值加上 byteCount.

ref long local = ref this.m_position;
long num = checked(local + (long)byteCount);
local = num;

这是 dotPeek 失败但 ILSpy 处理得很好的事情之一。您看到的是 += 运算符的编译器优化。而不是两次计算字段位置 - 一次获取值并再次存储它 - 编译器生成一次计算字段偏移量的代码,然后将其用于操作的两个部分。

您遇到的问题(未知的 ^ 运算符)很可能是 dotPeek 试图显示对 ref 变量的取消引用。当然,在 C# 中这不是必需的,我们只使用变量本身的名称。

改写为:

m_position += byteCount;

编译器将决定是否要添加该特定优化。