C# 內聯函數


  自從使用C#以來,很少用到內聯函數,甚至都沒想過,但從事數據采集處理過程中追求處理速度與代碼簡潔時,內聯無疑是一個利器。

  不同於C++的 inline 關鍵字,在C#中需要使用特性,使用方法如下:

  MethodImpl:實現了Method, Impl,implemented,其指示 CLR 即時編譯時的方式。
  MethodImplOptions:是一個枚舉類型,但允許按位組合。
    其中 AggressiveInlining 表示,The method should be inlined if possible.(即不保證一定會內聯)
class TestClass
{
//運行時才能決定是否執行內聯 [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
public ushort setUInt16(float src, ushort k = 1) {   return (ushort)(src * k); }   //對照 public uint setUInt32(float src, uint k = 10) { return (uint)(src * k); } } class Program { static DateTime StartTime = DateTime.Now; static void Main(string[] args) { TestClass my = new TestClass(); ushort ms = my.setUInt16(10, 2); uint mi = my.setUInt32(10.2f, 2); } }

C#在開發時編譯結果是中間語言,通過 ILDASM 查看,主要代碼如下:

.method public hidebysig instance uint16 setUInt16(float32 src, [opt] uint16 k) cil managed aggressiveinlining
{
  .param [2] = uint16(0x0001)
  // 代碼大小       6 (0x6)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  ldarg.2
  IL_0002:  conv.r4
  IL_0003:  mul
  IL_0004:  conv.u2
  IL_0005:  ret
} // end of method TestClass::setUInt16

.method public hidebysig instance uint32  setUInt32(float32 src, [opt] uint32 k) cil managed
{
  .param [2] = uint32(0x0000000A)
  // 代碼大小       7 (0x7)
  .maxstack  8
  IL_0000:  ldarg.1
  IL_0001:  ldarg.2
  IL_0002:  conv.r.un
  IL_0003:  conv.r4
  IL_0004:  mul
  IL_0005:  conv.u4
  IL_0006:  ret
} // end of method TestClass::setUInt32

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // 代碼大小       31 (0x1f)
  .maxstack  8
  IL_0000:  newobj     instance void S7SmartDriver.TestClass::.ctor()
  IL_0005:  dup
  IL_0006:  ldc.r4     10.
  IL_000b:  ldc.i4.2
  IL_000c:  callvirt   instance uint16 S7SmartDriver.TestClass::setUInt16(float32,
                                                                          uint16)
  IL_0011:  pop
  IL_0012:  ldc.r4     10.2
  IL_0017:  ldc.i4.2
  IL_0018:  callvirt   instance uint32 S7SmartDriver.TestClass::setUInt32(float32,
                                                                          uint32)
  IL_001d:  pop
  IL_001e:  ret
} // end of method Program::Main

在 setInt16 上加的 MethodImplOptions.AggressiveInlining 特性,對應於 IL 中的 aggressiveinlining, 而兩者在 Main 調用方式沒有區別。

在運行時CLR會將 IL 代碼即時編譯, 此時會根據CPU型號進行優化,至於在運行時是否真的進行了內聯,那就看CLR的心情啦。

 畢竟 aggressiveinlining 並非C++中的內聯,也非宏替換,只是 The method should be inlined if possible.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM