反编译源中不寻常的C#运算符......?

时间:2012-12-17 22:22:15

标签: c# syntax dotpeek

我刚刚使用DotPeek反编译了一些第三方来源来调试问题。输出代码包含一些不常见的操作符,AFAIK无效C#,所以我想知道它们是什么意思......

摘录看起来像(包括Dotpeek评论,因为它们可能相关);

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .
    .
    .        
    // ISSUE: explicit reference operation
    // ISSUE: variable of a reference type
    int& local = @Written;
    int num = SomeMethod();
    .
    .
    .
    // ISSUE: explicit reference operation
    ^local = num;
}

那么,那里有3个不寻常的运算符... int& = @Written似乎是在指定一个用@字符无意义命名的变量的指针?

但是什么是^local = num; ???

好的,这是ILSpy的等效片段,这更有意义,我想反编译到C#没有产生有效的等价物?

'C#'

 int& local = @Written;
 byte[] numArray2 = this.FInSpool;
 int num = (int) __Global.Min(numArray2 == null ? 0L : (long) numArray2.Length, (long) MaxSize);
 ^local = num;

IL

 byte[] expr_22 = this.FInSpool;
 Written = (int)__Global.Min((long)((expr_22 == null) ? 0 : expr_22.Length), (long)MaxSize);

所以,我猜'C#'不是很有效? IL将是有效的C#,不知道为什么DotPeek会产生它的输出。也许我会坚持ILSpy这个......?

3 个答案:

答案 0 :(得分:9)

如果你看一下原始的IL(来自ildasm,而不是通过IL Spy的C#等价物),这可能会帮助你看到反编译器试图说的内容。 “Out”参数使用(托管)类型引用表示,该引用未在C#中显式公开为类型。此类型的“实例”通常只能作为参数传递给接受类型引用的方法('ref'或'out'参数。)有关详细信息,请参阅OpCodes.Mkrefany

dotPeek抱怨的是这个'out'类型引用从参数存储到局部变量槽中,然后通过本地槽写入。 '@'和'^'是占位符,用于表示反编译器检测到的这种意外行为(ISSUE注释描述的行为)。

代码可能是从C ++ / CLI编译的,因此IL看起来与典型的C#编译器输出不同。也有可能这是混淆反编译器的某种程度的轻微混淆(虽然我不这么认为。)我不认为这在功能上与将参数从其参数直接加载到操作堆栈上有所不同(避免使用一个局部变量槽),但我可能是错的。

答案 1 :(得分:4)

在名称前添加@允许您为变量使用保留名称,例如,如果我想要一个名为return的变量,我需要这样做。

public int Weird()
{
    int @return = 0;
    return @return;
}

有关详细信息,请参阅this SO question


在名字前放^ ......嗯,没有头绪。 (将在我研究时更新我可以找到关于^在未被用作XOR时的含义的任何信息)

答案 2 :(得分:0)

这显然是一个反编译问题。由于广泛的语言支持反编译器到任何特定语言可能并不总能找到完全匹配,但仍尝试产生一些输出。反编译器可能会尝试产生一些等效的输出,就像在这种情况下可能是:

protected internal void DoReceive(ref byte[] Buffer, int MaxSize, out int Written)
{
    Written = 0;
    .        
    int num = SomeMethod();
    .
    Written = num;
}

但应该真的这样做吗?在这种情况下,反编译器实际上为您提供了一个提示,因此您可以决定这对您的特定情况是否重要,因为可能会有一些副作用。