如何用无效的引用语法重构这个反编译的 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;
编译器将决定是否要添加该特定优化。
反编译一个程序集,生成的代码有很多类似这样的方法:
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;
编译器将决定是否要添加该特定优化。