简体   繁体   English

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

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

After decompiling an assembly, the code it generated resulted in a lot of methods similar to this:反编译一个程序集后,它生成的代码产生了很多类似的方法:

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;
}

It's only the code starting at // ISSUE that's having a problem.只有从// ISSUE开始的代码有问题。 As you can see, it contains invalid syntax long& local;如您所见,它包含无效的语法long& local; . . I found this answer which does a great job of explaining what this is.我找到了这个答案,它很好地解释了这是什么。 After reading up on C# ref locals, I tried to refactor this method so that it can compile, but I haven't been successful.在阅读了 C# ref locals 之后,我尝试重构此方法以便它可以编译,但我没有成功。 The ^(local = ref this.m_position) part really does me in, as I'm not very strong when it comes to bitwise operations. ^(local = ref this.m_position)部分真的很适合我,因为我在按位运算方面不是很强大。

Could someone help me refactor those last three lines and explain to me how it works?有人可以帮我重构最后三行并向我解释它是如何工作的吗? This pattern appears almost verbatim in the decompiled code hundreds of times, so once I "grok" this one example, I should have no problem with the rest of it.这种模式在反编译的代码中几乎逐字出现数百次,所以一旦我“理解”这个例子,我应该对它的 rest 没有问题。

This is one of those things that dotPeek fails on but ILSpy handles nicely.这是 dotPeek 失败但 ILSpy 处理得很好的事情之一。 What you're seeing is a compiler optimization of the += operator.您看到的是+=运算符的编译器优化。 Rather than calculate the field location twice - once to fetch the value and again to store it - the compiler generates code that calculates the field offset one time then uses it for both parts of the operation.而不是计算字段位置两次 - 一次获取值并再次存储它 - 编译器生成计算字段偏移量的代码,然后将其用于操作的两个部分。

The bit you're having trouble with (the unknown ^ operator) is most likely an attempt by dotPeek to show a dereference of the ref variable.您遇到问题的位(未知的^运算符)很可能是 dotPeek 尝试显示 ref 变量的取消引用。 Of course this isn't necessary in C# where we just use the name of the variable itself.当然,在 C# 中这不是必需的,我们只使用变量本身的名称。

Just rewrite it as:只需将其重写为:

m_position += byteCount;

The compiler will decide whether or not it wants to add that particular optimization in.编译器将决定是否要添加该特定优化。

long& represents a reference type for a long and should be replaced with ref long . long&表示 long 的引用类型,应替换为ref long It's then assigning the address of the m_position field to the local variable (making local an alias for it), then checking for arithmetic overflow when adding the byte count to it.然后将m_position字段的地址分配给local变量(使local成为它的别名),然后在向其添加字节数时检查算术溢出。 Not entirely sure about the caret, in managed C++ it's a hat to instruct for GC of object, so I suppose that's what it's doing.不完全确定插入符号,在托管 C++ 中,它是指导 object GC 的帽子,所以我想这就是它在做什么。 When the arithmetic check completes successfully, the m_position field via local var is set to the current value plus byteCount .当算术检查成功完成时,通过local var 将m_position字段设置为当前值加上byteCount

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM