ILGenerator.Emit 方法

定義

放置指令到 Just-In-Time (JIT) 編譯器的 Microsoft Intermediate Language (MSIL) 資料流中。

多載

Emit(OpCode, LocalBuilder)

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定區域變數的索引。

Emit(OpCode, Type)

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定型別的中繼資料語彙基元。

Emit(OpCode, String)

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定字串的中繼資料語彙基元。

Emit(OpCode, Single)

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, SByte)

放置指定的指令和字元引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, MethodInfo)

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定方法的中繼資料語彙基元。

Emit(OpCode, SignatureHelper)

放置指定的指令和簽章語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, Label[])

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流中,並留下空間,以便在完成修復時加入標記。

Emit(OpCode, FieldInfo)

放置指定欄位的指定指令和中繼資料語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流中。

Emit(OpCode, ConstructorInfo)

放置指定建構函式的指定指令和中繼資料 (Metadata) 語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流中。

Emit(OpCode, Int64)

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, Int32)

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, Int16)

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, Double)

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode, Byte)

放置指定的指令和字元引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

Emit(OpCode)

放置指定的指令到指令資料流中。

Emit(OpCode, Label)

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流中,並留下空間,以便在完成修復時加入標記。

Emit(OpCode, LocalBuilder)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定區域變數的索引。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.LocalBuilder local);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

local
LocalBuilder

區域變數。

例外狀況

local 參數的父方法與這個 ILGenerator 的相關聯方法不相符。

localnull

opcode 是單一位元組的指令,而 local 表示索引大於 Byte.MaxValue 的區域變數。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Type)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定型別的中繼資料語彙基元。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, Type cls);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, Type cls);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

cls
Type

Type

例外狀況

clsnull

備註

指令值定義於 列舉中 OpCodes 。 的位置 cls 會記錄,以便在將模組保存到可攜式可執行檔時,視需要修補令牌, (PE) 檔案。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, String)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定字串的中繼資料語彙基元。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, string str);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, string str);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

str
String

要發出的 String

備註

指令值定義於 列舉中 OpCodes 。 如果模組保存到可攜式可執行檔 (PE) 檔案,則會記錄 位置 str 以供日後修正。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Single)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, float arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, float arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

arg
Single

Single 引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, SByte)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

重要

此 API 不符合 CLS 規範。

放置指定的指令和字元引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
[System.CLSCompliant(false)]
public void Emit (System.Reflection.Emit.OpCode opcode, sbyte arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

arg
SByte

字元引數,緊接指令之後立即被推入資料流。

屬性

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, MethodInfo)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流,然後放置指定方法的中繼資料語彙基元。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.MethodInfo meth);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

meth
MethodInfo

MethodInfo,表示方法。

例外狀況

methnull

meth 是泛型方法,其 IsGenericMethodDefinition 屬性為 false

備註

指令值定義於 列舉中 OpCodes

的位置 meth 會記錄,以便在將模組保存到可攜式可執行檔 (PE) 檔案時,視需要修補指令數據流。

如果 meth 表示泛型方法,它必須是泛型方法定義。 也就是說,其 MethodInfo.IsGenericMethodDefinition 屬性必須是 true

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, SignatureHelper)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和簽章語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.SignatureHelper signature);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

signature
SignatureHelper

Helper,用來建構簽章語彙基元。

例外狀況

signaturenull

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Label[])

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流中,並留下空間,以便在完成修復時加入標記。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label[] labels);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

labels
Label[]

標記物件陣列,要從這個位置分支至的。 會用到所有的標記。

例外狀況

connull。 此例外狀況是 .NET Framework 4 中的新功能。

範例

下列程式代碼範例說明如何建立具有跳躍數據表的動態方法。 跳躍數據表是使用的 Label陣列所建置。

C#
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

備註

發出參數數據表。

指令值定義於 列舉中 OpCodes

卷標是使用 來 DefineLabel 建立的,而且其位於數據流內的位置是使用 MarkLabel來修正。 如果使用單一位元組指令,標籤可以代表數據流最多 127 個字節的跳躍。 opcode 必須代表分支指令。 因為分支是相對指示, label 所以會在修正程序期間,以分支的正確位移取代。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, FieldInfo)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定欄位的指定指令和中繼資料語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流中。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.FieldInfo field);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

field
FieldInfo

FieldInfo,表示欄位。

備註

指令值定義於 列舉中 OpCodes 。 的位置 field 會記錄,以便在將模組保存到可攜式可執行檔 (PE) 檔案時,視需要修補指令數據流。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, ConstructorInfo)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定建構函式的指定指令和中繼資料 (Metadata) 語彙基元到指令的 Microsoft Intermediate Language (MSIL) 資料流中。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);
C#
[System.Runtime.InteropServices.ComVisible(true)]
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.ConstructorInfo con);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

con
ConstructorInfo

ConstructorInfo,表示建構函式。

屬性

例外狀況

connull。 此例外狀況是 .NET Framework 4 中的新功能。

備註

指令值定義於 列舉中 OpCodes

的位置 con 會記錄,以便在將模組保存到可攜式可執行檔時,視需要修補指令數據流, (PE) 檔案。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int64)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, long arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, long arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

arg
Int64

數字引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int32)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, int arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, int arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

arg
Int32

數字引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Int16)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, short arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, short arg);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

arg
Int16

Int 引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Double)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和數值引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, double arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, double arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。 已定義於 OpCodes 列舉型別中。

arg
Double

數字引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Byte)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令和字元引數到指令的 Microsoft Intermediate Language (MSIL) 資料流。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, byte arg);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, byte arg);

參數

opcode
OpCode

MSIL 指令,要放置到資料流中。

arg
Byte

字元引數,緊接指令之後立即被推入資料流。

備註

指令值定義於 列舉中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到指令資料流中。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode);

參數

opcode
OpCode

Microsoft Intermediate Language (MSIL) 指令,要放置到資料流中。

範例

下列程式代碼範例示範如何使用 Emit 透過的 ILGenerator實例產生 MSIL 輸出。

C#
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

備註

opcode如果參數需要自變數,呼叫端必須確定自變數長度符合宣告參數的長度。 否則,結果將無法預期。 例如,如果「發出」指令需要 2 位元組操作數,而呼叫端提供 4 位元組操作數,運行時間會將兩個額外的位元組發出至指令數據流。 這些額外的位元組將會是 Nop 指示。

指令值定義於 中 OpCodes

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Emit(OpCode, Label)

來源:
ILGenerator.cs
來源:
ILGenerator.cs
來源:
ILGenerator.cs

放置指定的指令到 Microsoft Intermediate Language (MSIL) 資料流中,並留下空間,以便在完成修復時加入標記。

C#
public virtual void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);
C#
public abstract void Emit (System.Reflection.Emit.OpCode opcode, System.Reflection.Emit.Label label);

參數

opcode
OpCode

要在資料流中發出的 MSIL 指令。

label
Label

標記,要從這個位置分支至的。

範例

下列程式代碼範例說明如何使用 jump 數據表建立動態方法。 跳躍數據表是使用的 Label陣列所建置。

C#
using System;
using System.Threading;
using System.Reflection;
using System.Reflection.Emit;

class DynamicJumpTableDemo
{
   public static Type BuildMyType()
   {
    AppDomain myDomain = Thread.GetDomain();
    AssemblyName myAsmName = new AssemblyName();
    myAsmName.Name = "MyDynamicAssembly";

    AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly(
                        myAsmName,
                        AssemblyBuilderAccess.Run);
    ModuleBuilder myModBuilder = myAsmBuilder.DefineDynamicModule(
                        "MyJumpTableDemo");

    TypeBuilder myTypeBuilder = myModBuilder.DefineType("JumpTableDemo",
                            TypeAttributes.Public);
    MethodBuilder myMthdBuilder = myTypeBuilder.DefineMethod("SwitchMe",
                             MethodAttributes.Public |
                             MethodAttributes.Static,
                                             typeof(string),
                                             new Type[] {typeof(int)});

    ILGenerator myIL = myMthdBuilder.GetILGenerator();

    Label defaultCase = myIL.DefineLabel();	
    Label endOfMethod = myIL.DefineLabel();	

    // We are initializing our jump table. Note that the labels
    // will be placed later using the MarkLabel method.

    Label[] jumpTable = new Label[] { myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel(),
                      myIL.DefineLabel() };

    // arg0, the number we passed, is pushed onto the stack.
    // In this case, due to the design of the code sample,
    // the value pushed onto the stack happens to match the
    // index of the label (in IL terms, the index of the offset
    // in the jump table). If this is not the case, such as
    // when switching based on non-integer values, rules for the correspondence
    // between the possible case values and each index of the offsets
    // must be established outside of the ILGenerator.Emit calls,
    // much as a compiler would.

    myIL.Emit(OpCodes.Ldarg_0);
    myIL.Emit(OpCodes.Switch, jumpTable);
    
    // Branch on default case
    myIL.Emit(OpCodes.Br_S, defaultCase);

    // Case arg0 = 0
    myIL.MarkLabel(jumpTable[0]);
    myIL.Emit(OpCodes.Ldstr, "are no bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 1
    myIL.MarkLabel(jumpTable[1]);
    myIL.Emit(OpCodes.Ldstr, "is one banana");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 2
    myIL.MarkLabel(jumpTable[2]);
    myIL.Emit(OpCodes.Ldstr, "are two bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 3
    myIL.MarkLabel(jumpTable[3]);
    myIL.Emit(OpCodes.Ldstr, "are three bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Case arg0 = 4
    myIL.MarkLabel(jumpTable[4]);
    myIL.Emit(OpCodes.Ldstr, "are four bananas");
    myIL.Emit(OpCodes.Br_S, endOfMethod);

    // Default case
    myIL.MarkLabel(defaultCase);
    myIL.Emit(OpCodes.Ldstr, "are many bananas");

    myIL.MarkLabel(endOfMethod);
    myIL.Emit(OpCodes.Ret);
    
    return myTypeBuilder.CreateType();
   }

   public static void Main()
   {
    Type myType = BuildMyType();
    
    Console.Write("Enter an integer between 0 and 5: ");
    int theValue = Convert.ToInt32(Console.ReadLine());

    Console.WriteLine("---");
    Object myInstance = Activator.CreateInstance(myType, new object[0]);	
    Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe",
                               BindingFlags.InvokeMethod,
                               null,
                               myInstance,
                               new object[] {theValue}));
   }
}

備註

指令值定義於 列舉中 OpCodes

卷標是使用 DefineLabel建立的,而且其數據流內的位置是使用 MarkLabel來修正的。 如果使用單一位元組指令,標籤最多可以代表數據流 127 個字節的跳躍。 opcode 必須代表分支指令。 因為分支是相對指示, label 所以會在修正程序期間,以分支的正確位移取代。

適用於

.NET 9 和其他版本
產品 版本
.NET Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9
.NET Framework 1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1