OpCodes.Switch フィールド
アセンブリ: mscorlib (mscorlib.dll 内)


命令の 16 進数の形式、MSIL (Microsoft Intermediate Language) アセンブリ形式、および簡単な説明の一覧を次の表に示します。
switch 命令は、ジャンプ テーブルを実装します。命令の書式は、ジャンプ先の数 N を表す unsigned int32 の後に、ジャンプ先を指定する N int32 値が続きます。これらのジャンプ先は、この switch 命令の次の命令の先頭からのオフセット (正または負) として表されます。
switch 命令は、スタックから値をポップし、符号なし整数として N と比較します。値が N 未満の場合、インデックスがこの値であるターゲットに実行が転送されます。ターゲットの番号は 0 から始まります。たとえば、値が 0 の場合は最初のターゲット、1 の場合は 2 番目のターゲットとなり、以下同様に続きます。値が N を超える場合は、次の命令で実行が継続されます (フォール スルー)。
ターゲット命令に 1 つ以上のプリフィックス コードがある場合は、最初のプリフィックスだけに制御を転送できます。
この命令では、try、catch、filter、finally の各ブロックの内外への制御の転送は実行できません。このような転送は厳重に制限されており、この命令ではなく leave 命令を使用する必要があります。
switch オペコードを使用できる Emit メソッド オーバーロードを次に示します。Label[] 引数は、32 ビット オフセットを表す Labels の配列です。
-
ILGenerator.Emit(OpCode, Label[])

Switch オペコードを使用し、Label の配列を使用してジャンプ テーブルを生成する方法を次のコード サンプルに示します。
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
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})); } }
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 ) ); }
import System .* ; import System.Threading .* ; import System.Reflection .* ; import System.Reflection.Emit .* ; class DynamicJumpTableDemo { public static Type BuildMyType() { AppDomain myDomain = System.Threading.Thread.GetDomain(); AssemblyName myAsmName = new AssemblyName(); myAsmName.set_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, String.class.ToType(),new Type[] { int.class.ToType() }); 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(); } //BuildMyType public static void main(String[] args) { 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[]{(Int32)(theValue)})); } //main } //DynamicJumpTableDemo

Windows 98, Windows 2000 SP4, Windows Millennium Edition, Windows Server 2003, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP SP2, Windows XP Starter Edition
開発プラットフォームの中には、.NET Framework によってサポートされていないバージョンがあります。サポートされているバージョンについては、「システム要件」を参照してください。


Weblioに収録されているすべての辞書からOpCodes.Switch フィールドを検索する場合は、下記のリンクをクリックしてください。

- OpCodes.Switch フィールドのページへのリンク