所以我看了一下 MethodImplAttribute我遇到了MethodImplOptions.AggressiveInlining这被描述为:
The method should be inlined if possible.
哦哦,我心想,这听起来很有趣——我可以假装自己比编译器更聪明,并使用我邪恶意志的力量和几个方括号强制代码内联,哈,哈,哈。 ..
因此我启动了 Visual Studio 2013,创建了一个控制台应用程序,将 .NET 版本设置为 4.5.1 并编写了程序以结束所有程序(当然是在 Release
模式下编译) :
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
public static class SoHelpful
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetSomeValueProbablyTwelve()
{
return 12;
}
[MethodImpl(MethodImplOptions.NoInlining)]
public static int GetSomeValueLikelyThirteen()
{
return 13;
}
public static int GetSomeValueMaybeItIsTwentyEight()
{
return 29;
}
}
class Program
{
static void Main()
{
int twelve = SoHelpful.GetSomeValueProbablyTwelve();
int thirteen = SoHelpful.GetSomeValueLikelyThirteen();
int twentyNine = SoHelpful.GetSomeValueMaybeItIsTwentyEight();
Console.WriteLine((twelve + thirteen + twentyNine));
}
}
}
现在,如果我快速执行 ildasm,我会看到:
.class public abstract auto ansi sealed beforefieldinit ConsoleApplication1.SoHelpful
extends [mscorlib]System.Object
{
.method public hidebysig static int32 GetSomeValueProbablyTwelve() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 12
IL_0002: ret
} // end of method SoHelpful::GetSomeValueProbablyTwelve
.method public hidebysig static int32 GetSomeValueLikelyThirteen() cil managed noinlining
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 13
IL_0002: ret
} // end of method SoHelpful::GetSomeValueLikelyThirteen
.method public hidebysig static int32 GetSomeValueMaybeItIsTwentyEight() cil managed
{
// Code size 3 (0x3)
.maxstack 8
IL_0000: ldc.i4.s 29
IL_0002: ret
} // end of method SoHelpful::GetSomeValueMaybeItIsTwentyEight
} // end of class ConsoleApplication1.SoHelpful
.class private auto ansi beforefieldinit ConsoleApplication1.Program
extends [mscorlib]System.Object
{
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 29 (0x1d)
.maxstack 2
.locals init ([0] int32 twelve,
[1] int32 thirteen,
[2] int32 twentyNine)
IL_0000: call int32 ConsoleApplication1.SoHelpful::GetSomeValueProbablyTwelve()
IL_0005: stloc.0
IL_0006: call int32 ConsoleApplication1.SoHelpful::GetSomeValueLikelyThirteen()
IL_000b: stloc.1
IL_000c: call int32 ConsoleApplication1.SoHelpful::GetSomeValueMaybeItIsTwentyEight()
IL_0011: stloc.2
IL_0012: ldloc.0
IL_0013: ldloc.1
IL_0014: add
IL_0015: ldloc.2
IL_0016: add
IL_0017: call void [mscorlib]System.Console::WriteLine(int32)
IL_001c: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class ConsoleApplication1.Program
有意思,所以定义了三个方法:
.method public hidebysig static int32 GetSomeValueLikelyThirteen() cil managed noinlining
.method public hidebysig static int32 GetSomeValueProbablyTwelve() cil managed
.method public hidebysig static int32 GetSomeValueMaybeItIsTwentyEight() cil managed
因此,看起来我的主动内联属性丢失了。
我可以在 GetSomeValueLikelyThirteen
上看到 noinlining
,但 GetSomeValueProbablyTwelve
和 GetSomeValueMaybeItIsTwentyEight
是相同的。
所以发生了什么?我想有几种可能性:
- C# 编译器已经意识到
GetSomeValueProbablyTwelve
不能被内联,所以不会用我愚蠢的属性白痴来麻烦 JIT。 - C# 编译器已经意识到
GetSomeValueMaybeItIsTwentyEight
可以被内联,这就是为什么它在 IL 中与GetSomeValueProbablyTwelve
相同(所以我的归因在很大程度上是毫无意义和愚蠢的这种情况也是如此)。 - 有一些编译设置或我必须调整的东西才能识别属性。
- 它根本没有在
C#
中实现。 - 我发现了一个错误
- 其他
那么,有人知道它是什么吗?
最佳答案
MethodImplAttributes.AggressiveInlining
编译为 MethodDef 元数据表(ECMA-335 Partition II §22.26)的 ImplFlags 列中的标志。此属性的值在 Partition II §23.1.11 中列出,但 AggressiveInlining
未记录(表中不存在 0x0100 的值)。
在编译过程中,编译器会从元数据中删除属性本身。如果方法的 ImplFlags 中设置了 0x0100 位,则反汇编器必须实现特殊逻辑来添加属性。
关于c# - MethodImpl(AggressiveInlining) - 它有多激进?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20517103/