OpCodes.Switch OpCodes.Switch OpCodes.Switch OpCodes.Switch Field

定義

ジャンプ テーブルを実装します。 Implements a jump table.

public: static initonly System::Reflection::Emit::OpCode Switch;
public static readonly System.Reflection.Emit.OpCode Switch;
 staticval mutable Switch : System.Reflection.Emit.OpCode
Public Shared ReadOnly Switch As OpCode 
フィールド値

次のコード サンプルの使用を示しています、Switchの配列を使用してジャンプ テーブルを生成するオペコードLabelします。The following code sample illustrates the use of the Switch opcode to generate a jump table using an array of Label.

using namespace System;
using namespace System::Threading;
using namespace System::Reflection;
using namespace System::Reflection::Emit;
Type^ BuildMyType()
{
   AppDomain^ myDomain = Thread::GetDomain();
   AssemblyName^ myAsmName = gcnew AssemblyName;
   myAsmName->Name = "MyDynamicAssembly";
   AssemblyBuilder^ myAsmBuilder = myDomain->DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess::Run );
   ModuleBuilder^ myModBuilder = myAsmBuilder->DefineDynamicModule( "MyJumpTableDemo" );
   TypeBuilder^ myTypeBuilder = myModBuilder->DefineType( "JumpTableDemo", TypeAttributes::Public );
   array<Type^>^temp0 = {int::typeid};
   MethodBuilder^ myMthdBuilder = myTypeBuilder->DefineMethod( "SwitchMe", static_cast<MethodAttributes>(MethodAttributes::Public | MethodAttributes::Static), String::typeid, temp0 );
   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.
   array<Label>^jumpTable = gcnew array<Label>(5);
   jumpTable[ 0 ] = myIL->DefineLabel();
   jumpTable[ 1 ] = myIL->DefineLabel();
   jumpTable[ 2 ] = myIL->DefineLabel();
   jumpTable[ 3 ] = myIL->DefineLabel();
   jumpTable[ 4 ] = 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();
}

int 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, gcnew array<Object^>(0) );
   array<Object^>^temp1 = {theValue};
   Console::WriteLine( "Yes, there {0} today!", myType->InvokeMember( "SwitchMe", BindingFlags::InvokeMethod, nullptr, myInstance, temp1 ) );
}


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

}


Imports System
Imports System.Threading
Imports System.Reflection
Imports System.Reflection.Emit

 _

Class DynamicJumpTableDemo
   
   Public Shared Function BuildMyType() As Type

      Dim myDomain As AppDomain = Thread.GetDomain()
      Dim myAsmName As New AssemblyName()
      myAsmName.Name = "MyDynamicAssembly"
      
      Dim myAsmBuilder As AssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, _
							AssemblyBuilderAccess.Run)
      Dim myModBuilder As ModuleBuilder = myAsmBuilder.DefineDynamicModule("MyJumpTableDemo")
      
      Dim myTypeBuilder As TypeBuilder = myModBuilder.DefineType("JumpTableDemo", _
								 TypeAttributes.Public)
      Dim myMthdBuilder As MethodBuilder = myTypeBuilder.DefineMethod("SwitchMe", _
						MethodAttributes.Public Or MethodAttributes.Static, _
						GetType(String), New Type() {GetType(Integer)})
      
      Dim myIL As ILGenerator = myMthdBuilder.GetILGenerator()
      
      Dim defaultCase As Label = myIL.DefineLabel()
      Dim endOfMethod As Label = myIL.DefineLabel()
      
      ' We are initializing our jump table. Note that the labels
      ' will be placed later using the MarkLabel method. 

      Dim jumpTable() As 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()

   End Function 'BuildMyType
    
   
   Public Shared Sub Main()

      Dim myType As Type = BuildMyType()
      
      Console.Write("Enter an integer between 0 and 5: ")
      Dim theValue As Integer = Convert.ToInt32(Console.ReadLine())
      
      Console.WriteLine("---")
      Dim myInstance As [Object] = Activator.CreateInstance(myType, New Object() {})
      Console.WriteLine("Yes, there {0} today!", myType.InvokeMember("SwitchMe", _
						 BindingFlags.InvokeMethod, Nothing, _
					         myInstance, New Object() {theValue}))

   End Sub 'Main

End Class 'DynamicJumpTableDemo

注釈

次の表は、命令の 16 進数と簡単なリファレンス概要と共に、Microsoft Intermediate Language (MSIL) アセンブリの形式を示します。The following table lists the instruction's hexadecimal and Microsoft Intermediate Language (MSIL) assembly format, along with a brief reference summary:

形式Format アセンブリの形式Assembly Format 説明Description
45 < unsigned int32 > < int32 >... < int32 >45 < unsigned int32 > < int32 >... < int32 > 切り替え (Nt1t2.tN)switch (N, t1, t2... tN) いずれかにジャンプN値。Jumps to one of N values.

履歴の移行動作を順番には。The stack transitional behavior, in sequential order, is:

  1. 値は、スタックにプッシュされます。A value is pushed onto the stack.

  2. 値がスタックからポップし、実行は、値がインデックスを指定されたオフセット位置に命令する転送より小さいNします。The value is popped off the stack and execution is transferred to the instruction at the offset indexed by the value, where the value is less than N.

switch命令がジャンプ テーブルを実装します。The switch instruction implements a jump table. 命令の形式は、unsigned int32ターゲットの数を表すN、その後にNint32 の値を指定するターゲットを移動します。The format of the instruction is an unsigned int32 representing the number of targets N, followed by N int32 values specifying jump targets. これらのターゲットは、これを次の命令の先頭からのオフセット (正または負の値) として表されますswitch命令。These targets are represented as offsets (positive or negative) from the beginning of the instruction following this switch instruction.

switch命令は、値をスタックからポップし、符号なし整数として、比較Nします。The switch instruction pops a value off the stack and compares it, as an unsigned integer, to N. 値の場合より小さいNターゲットが 0 から番号が、値によってインデックス付けされたターゲットに転送される実行 (値 0 は最初のターゲットを受け取り、値 1 と 2 つ目のターゲットなど)。If value is less than N, execution is transferred to the target indexed by value, where targets are numbered from 0 (for example, a value of 0 takes the first target, a value of 1 takes the second target, and so on). 値がより大きいか等しい場合N、次の命令 (フォール スルー) で実行が続行されます。If the value is greater than or equal to N, execution continues at the next instruction (fall through).

最初の制御を転送できますのみ、ターゲット命令に 1 つ以上のプレフィックス コードがある場合は、これらのプレフィックス。If the target instruction has one or more prefix codes, control can only be transferred to the first of these prefixes.

転送の入出力制御trycatchfilter、およびfinallyこの命令によってブロックを実行することはできません。Control transfers into and out of try, catch, filter, and finally blocks cannot be performed by this instruction. (このような転送は厳しく制限されているし、leave 命令を代わりに使用する必要があります。)(Such transfers are severely restricted and must use the leave instruction instead).

Emitメソッドのオーバー ロードを使用できる、 switch opcode です。The following Emit method overload can use the switch opcode. Label[]引数は、32 ビットのオフセットを表すラベルの配列。The Label[] argument is an array of Labels representing 32-bit offsets.

  • (オペコード、Label[]) ILGenerator.EmitILGenerator.Emit(OpCode, Label[])

適用対象