ジェネリック クラス (C++/CLI)Generic Classes (C++/CLI)

ジェネリック クラスは、次の構文を使用して宣言されます。A generic class is declared using the following form:

構文Syntax

[attributes]
generic <class-key type-parameter-identifier(s)>
[constraint-clauses]
[accessibility-modifiers] ref class identifier  [modifiers]
[: base-list]
{
class-body
} [declarators] [;]

解説Remarks

上記の構文では、次の用語が使用されています。In the above syntax, the following terms are used:

attributesattributes
(省略可能) 追加の宣言情報。(Optional) Additional declarative information. 属性と属性クラスについては、「属性」を参照してください。For more information on attributes and attribute classes, see Attributes.

class-keyclass-key
class または**typename**Either class or typename

type-parameter-identifier(s)。型パラメーターの名前を指定する識別子のコンマ区切りの一覧。type-parameter-identifier(s), Comma-separated list of identifiers specifying the names of the type parameters.

constraint-clausesconstraint-clauses
型パラメーターの制約を指定する where 句の一覧 (コンマ区切りではありません)。A list (not comma-separated) of where clauses specifying the constraints for the type parameters. 次の書式を使用します。Takes the form:

ここ***で、型パラメーターの識別子 : 制約リスト***... where type-parameter-identifier : constraint-list ...

constraint-listconstraint-list
クラスまたはインターフェイス[ , ...]class-or-interface[, ...]

accessibility-modifiersaccessibility-modifiers
ジェネリック クラスのアクセシビリティ修飾子。Accessibility modifiers for the generic class. Windows ランタイムの場合、許可される修飾子はだけ private です。For the Windows Runtime, the only allowed modifier is private. 共通言語ランタイムの場合、許可される修飾子は privatepublic です。For the common language runtime, the allowed modifiers are private and public.

identifieridentifier
ジェネリック クラスの名前。任意の有効な C++ 識別子です。The name of the generic class, any valid C++ identifier.

modifiers
(省略可能) 許可される修飾子は sealedabstract です。(Optional) Allowed modifiers include sealed and abstract.

base-listbase-list
1 つの基底クラスと、実装されるすべてのインターフェイスを含む、コンマ区切りの一覧。A list that contains the one base class and any implemented interfaces, all separated by commas.

class-bodyclass-body
フィールド、メンバー関数などを含む、クラスの本文。The body of the class, containing fields, member functions, etc.

declaratorsdeclarators
この型の任意の変数の宣言。Declarations of any variables of this type. 例: ^ identifier[ , ...]For example: ^identifier[, ...]

このようなジェネリッククラスを宣言できます (の代わりにキーワードを使用すること class もでき typename ます)。You can declare generic classes such as these (note that the keyword class may be used instead of typename). この例では、ItemTypeKeyType、および ValueType は、型の指定場所では不明な型です。In this example, ItemType, KeyType and ValueType are unknown types that are specified at the point where the type. HashTable<int, int> は、ジェネリック型 HashTable<KeyType, ValueType> の構築型です。HashTable<int, int> is a constructed type of the generic type HashTable<KeyType, ValueType>. 1 つのジェネリック型から、多数の異なる構築型を構築できます。A number of different constructed types can be constructed from a single generic type. ジェネリック クラスから構築された構築型は、他の ref クラス型のように扱われます。Constructed types constructed from generic classes are treated like any other ref class type.

// generic_classes_1.cpp
// compile with: /clr
using namespace System;
generic <typename ItemType>
ref struct Stack {
   // ItemType may be used as a type here
   void Add(ItemType item) {}
};

generic <typename KeyType, typename ValueType>
ref class HashTable {};

// The keyword class may be used instead of typename:
generic <class ListItem>
ref class List {};

int main() {
   HashTable<int, Decimal>^ g1 = gcnew HashTable<int, Decimal>();
}

値型 (やなどの組み込み型 int また double はユーザー定義値型) と参照型のどちらも、ジェネリック型引数として使用できます。Both value types (either built-in types such as int or double, or user-defined value types) and reference types may be used as a generic type argument. ジェネリック定義内の構文は、どちらでも同じです。The syntax within the generic definition is the same regardless. 構文上、不明な型は、参照型であるかのように扱われます。Syntactically, the unknown type is treated as if it were a reference type. ただし、ランタイムは、実際に使用される型が値型であるかどうかを判断し、メンバーに直接アクセスするために生成される適切なコードに置換できます。However, the runtime is able to determine that if the type actually used is a value type and substitute the appropriate generated code for direct access to members. ジェネリック型引数として使用される値型はボックス化されないため、ボックス化に関連するパフォーマンスの低下は発生しません。Value types used as generic type arguments are not boxed and so do not suffer the performance penalty associated with boxing. ジェネリックの本文内で使用される構文では、. ではなく、T^-> にする必要があります。The syntax used within the body of the generic should be T^ and -> instead of .. 型パラメーターでの ref new、gcnew の使用は、値引数が値型の場合は、ランタイムによって、値型の単純な作成であると適切に解釈されます。Any use of ref new, gcnew for the type parameter will be appropriately interpreted by the runtime as the simple creation of a value type if the type argument is a value type.

型パラメーターで使用できる型に対して、ジェネリック型パラメーターの制約 (C++/CLI)があるジェネリック クラスを宣言することもできます。You can also declare a generic class with Constraints on Generic Type Parameters (C++/CLI) on the types that can be used for the type parameter. 次の例では、ItemType で使用される任意の型で IItem インターフェイスを実装する必要があります。In the following example any type used for ItemType must implement the IItem interface. を実装していないなどを使用しようとすると、 int IItem 型引数が制約を満たしていないため、コンパイル時エラーが発生します。Attempting to use int, for example, which does not implement IItem, would produce a compile-time error because the type argument does not satisfy the constraint.

// generic_classes_2.cpp
// compile with: /clr /c
interface class IItem {};
generic <class ItemType>
where ItemType : IItem
ref class Stack {};

同じ名前空間のジェネリック クラスは、型パラメーターの数または型を変更するだけではオーバーロードできません。Generic classes in the same namespace cannot be overloaded by only changing the number or the types of type parameters. ただし、各クラスが別の名前空間にある場合はオーバーロードできます。However, if each class lives in a different namespace, they can be overloaded. たとえば、名前空間 AB にある次の 2 つのクラス (MyClassMyClass<ItemType>) について考えます。For example, consider the following two classes, MyClass and MyClass<ItemType>, in the namespaces A and B. この 2 つのクラスは、3 番目の名前空間 C 内でオーバーロードできます。The two classes can then be overloaded in a third namespace C:

// generic_classes_3.cpp
// compile with: /clr /c
namespace A {
   ref class MyClass {};
}

namespace B {
   generic <typename ItemType>
   ref class MyClass2 { };
}

namespace C {
   using namespace A;
   using namespace B;

   ref class Test {
      static void F() {
         MyClass^ m1 = gcnew MyClass();   // OK
         MyClass2<int>^ m2 = gcnew MyClass2<int>();   // OK
      }
   };
}

基底クラスと基底インターフェイスを型パラメーターにすることはできません。The base class and base interfaces cannot be type parameters. ただし、基底クラスでは、次の例のように、引数として型パラメーターを含めることができます。However, the base class can involve the type parameter as an argument, as in the following case:

// generic_classes_4.cpp
// compile with: /clr /c
generic <typename ItemType>
interface class IInterface {};

generic <typename ItemType>
ref class MyClass : IInterface<ItemType> {};

コンストラクターとデストラクターは、オブジェクト インスタンスごとに (通常どおりに) 1 回実行されます。静的コンストラクターは、構築型ごとに 1 回実行されます。Constructors and destructors are executed once for each object instance (as usual); static constructors are executed once for each constructed type.

ジェネリック クラスのフィールドFields in Generic Classes

このセクションでは、ジェネリック クラスのインスタンスと静的フィールドの使用を示します。This section demonstrates the use of instance and static fields in generic classes.

インスタンス変数Instance Variables

ジェネリック クラスのインスタンス変数は、外側のクラスからの型と任意の型パラメーターを含む変数初期化子を持つことができます。Instance variables of a generic class can have types and variable initializers that include any type parameters from the enclosing class.

例: 異なるジェネリッククラスExample: Different generic classes

次の例では、ジェネリッククラス MyClass の3つの異なるインスタンス <ItemType> が、適切な型引数 ( intdouble 、および string) を使用して作成されます。In the following example, three different instances of the generic class, MyClass<ItemType>, are created by using the appropriate type arguments (int, double, and string).

// generics_instance_fields1.cpp
// compile with: /clr
// Instance fields on generic classes
using namespace System;

generic <typename ItemType>
ref class MyClass {
// Field of the type ItemType:
public :
   ItemType field1;
   // Constructor using a parameter of the type ItemType:
   MyClass(ItemType p) {
   field1 = p;
   }
};

int main() {
   // Instantiate an instance with an integer field:
   MyClass<int>^ myObj1 = gcnew MyClass<int>(123);
   Console::WriteLine("Integer field = {0}", myObj1->field1);

   // Instantiate an instance with a double field:
   MyClass<double>^ myObj2 = gcnew MyClass<double>(1.23);
   Console::WriteLine("Double field = {0}", myObj2->field1);

   // Instantiate an instance with a String field:
   MyClass<String^>^ myObj3 = gcnew MyClass<String^>("ABC");
   Console::WriteLine("String field = {0}", myObj3->field1);
   }
Integer field = 123
Double field = 1.23
String field = ABC

静的変数Static Variables

新しいジェネリック型の作成時に、静的変数の新しいインスタンスが作成され、その型の任意の静的コンストラクターが実行されます。On the creation of a new generic type, new instances of any static variables are created and any static constructor for that type is executed.

静的変数では、外側のクラスから任意の型パラメーターを使用できます。Static variables can use any type parameters from the enclosing class.

例: 静的変数を使用するExample: Use static variables

次の例では、静的コンストラクター内での静的フィールドと汎用クラスの使用を示します。The following example demonstrates using static fields and a static constructor within a generic class.

// generics_static2.cpp
// compile with: /clr
using namespace System;

interface class ILog {
   void Write(String^ s);
};

ref class DateTimeLog : ILog {
public:
   virtual void Write(String^ s) {
      Console::WriteLine( "{0}\t{1}", DateTime::Now, s);
   }
};

ref class PlainLog : ILog {
public:
   virtual void Write(String^ s) { Console::WriteLine(s); }
};

generic <typename LogType>
where LogType : ILog
ref class G {
   static LogType s_log;

public:
   G(){}
   void SetLog(LogType log) { s_log = log; }
   void F() { s_log->Write("Test1"); }
   static G() { Console::WriteLine("Static constructor called."); }
};

int main() {
   G<PlainLog^>^ g1 = gcnew G<PlainLog^>();
   g1->SetLog(gcnew PlainLog());
   g1->F();

   G<DateTimeLog^>^ g2 = gcnew G<DateTimeLog^>();
   g2->SetLog(gcnew DateTimeLog());

   // prints date
   // g2->F();
}
Static constructor called.
Static constructor called.
Static constructor called.
Test1

ジェネリック クラスのメソッドMethods in Generic Classes

ジェネリック クラスのメソッドそのものをジェネリックにすることができます。非ジェネリック メソッドは、クラスの型パラメーターによって暗黙的にパラメーター化されます。Methods in generic classes can be generic themselves; non-generic methods will be implicitly parameterized by the class type parameter.

ジェネリック クラス内のメソッドには、次の特別なルールが適用されます。The following special rules apply to methods within generic classes:

  • ジェネリック クラスのメソッドでは、パラメーター、戻り値の型、またはローカル変数として型パラメーターを使用できます。Methods in generic classes can use type parameters as parameters, return types, or local variables.

  • ジェネリック クラスのメソッドでは、パラメーター、戻り値の型、またはローカル変数として、オープンまたはクローズ構築型を使用できます。Methods in generic classes can use open or closed constructed types as parameters, return types, or local variables.

ジェネリック クラスの非ジェネリック メソッドNon-Generic Methods in Generic Classes

追加の型パラメーターを持たないジェネリック クラスのメソッドは、通常は非ジェネリックとして参照されますが、それらは外側のジェネリック クラスによって暗黙的にパラメーター化されます。Methods in generic classes that have no additional type parameters are usually referred to as non-generic although they are implicitly parameterized by the enclosing generic class.

非ジェネリック メソッドのシグネチャには、外側のクラスの 1 つまたは複数の型パラメーターを含めることができます(直接的に、またはオープン構築型のいずれか)。The signature of a non-generic method can include one or more type parameters of the enclosing class, either directly or in an open constructed type. 次に例を示します。For example:

void MyMethod(MyClass<ItemType> x) {}

このようなメソッドの本文でも、これらの型パラメーターを使用できます。The body of such methods can also use these type parameters.

例: 非ジェネリックメソッドの宣言Example: Declare non-generic method

次の例では、ジェネリック クラス MyClass<ItemType> 内に非ジェネリック メソッド ProtectData を宣言します。The following example declares a non-generic method, ProtectData, inside a generic class, MyClass<ItemType>. このメソッドは、クラス型パラメーター ItemType をオープン構築型のシグニチャ内で使用します。The method uses the class type parameter ItemType in its signature in an open constructed type.

// generics_non_generic_methods1.cpp
// compile with: /clr
// Non-generic methods within a generic class.
using namespace System;

generic <typename ItemType>
ref class MyClass {
public:
   String^ name;
   ItemType data;

   MyClass(ItemType x) {
      data = x;
   }

   // Non-generic method using the type parameter:
   virtual void ProtectData(MyClass<ItemType>^ x) {
      data = x->data;
   }
};

// ItemType defined as String^
ref class MyMainClass: MyClass<String^> {
public:
   // Passing "123.00" to the constructor:
   MyMainClass(): MyClass<String^>("123.00") {
      name = "Jeff Smith";
   }

   virtual void ProtectData(MyClass<String^>^ x) override {
      x->data = String::Format("${0}**", x->data);
   }

   static void Main() {
      MyMainClass^ x1 = gcnew MyMainClass();

      x1->ProtectData(x1);
      Console::WriteLine("Name: {0}", x1->name);
      Console::WriteLine("Amount: {0}", x1->data);
   }
};

int main() {
   MyMainClass::Main();
}
Name: Jeff Smith
Amount: $123.00**

ジェネリック クラスのジェネリック メソッドGeneric Methods in Generic Classes

ジェネリックと非ジェネリック クラスの両方でジェネリック メソッドを宣言できます。You can declare generic methods in both generic and non-generic classes. 次に例を示します。For example:

例: ジェネリックメソッドと非ジェネリックメソッドを宣言するExample: Declare generic and non-generic methods

// generics_method2.cpp
// compile with: /clr /c
generic <typename Type1>
ref class G {
public:
   // Generic method having a type parameter
   // from the class, Type1, and its own type
   // parameter, Type2
   generic <typename Type2>
   void Method1(Type1 t1, Type2 t2) { F(t1, t2); }

   // Non-generic method:
   // Can use the class type param, Type1, but not Type2.
   void Method2(Type1 t1) { F(t1, t1); }

   void F(Object^ o1, Object^ o2) {}
};

非ジェネリック メソッドは、クラスの型パラメーターによってパラメーター化されるが追加の型パラメーターを持たないという意味ではジェネリックのままです。The non-generic method is still generic in the sense that it is parameterized by the class's type parameter, but it has no additional type parameters.

ジェネリック クラスのメソッドのすべての型は、静的、インスタンス、および仮想メソッドを含むジェネリックにすることができます。All types of methods in generic classes can be generic, including static, instance, and virtual methods.

例: ジェネリックメソッドの宣言と使用Example: Declare and use generic methods

次の例では、ジェネリック クラス内でジェネリック メソッドを宣言して使用することを示します。The following example demonstrates declaring and using generic methods within generic classes:

// generics_generic_method2.cpp
// compile with: /clr
using namespace System;
generic <class ItemType>
ref class MyClass {
public:
   // Declare a generic method member.
   generic <class Type1>
   String^ MyMethod(ItemType item, Type1 t) {
      return String::Concat(item->ToString(), t->ToString());
   }
};

int main() {
   // Create instances using different types.
   MyClass<int>^ myObj1 = gcnew MyClass<int>();
   MyClass<String^>^ myObj2 = gcnew MyClass<String^>();
   MyClass<String^>^ myObj3 = gcnew MyClass<String^>();

   // Calling MyMethod using two integers.
   Console::WriteLine("MyMethod returned: {0}",
            myObj1->MyMethod<int>(1, 2));

   // Calling MyMethod using an integer and a string.
   Console::WriteLine("MyMethod returned: {0}",
            myObj2->MyMethod<int>("Hello #", 1));

   // Calling MyMethod using two strings.
   Console::WriteLine("MyMethod returned: {0}",
       myObj3->MyMethod<String^>("Hello ", "World!"));

   // generic methods can be called without specifying type arguments
   myObj1->MyMethod<int>(1, 2);
   myObj2->MyMethod<int>("Hello #", 1);
   myObj3->MyMethod<String^>("Hello ", "World!");
}
MyMethod returned: 12
MyMethod returned: Hello #1
MyMethod returned: Hello World!

ジェネリック クラスでの入れ子にされた型の使用Using Nested Types in Generic Classes

通常のクラスと同様、ジェネリック クラス内に他の型を宣言できます。Just as with ordinary classes, you can declare other types inside a generic class. 入れ子になったクラス宣言は、外側のクラス宣言の型パラメーターによって暗黙的にパラメーター化されます。The nested class declaration is implicitly parameterized by the type parameters of the outer class declaration. そのため、個別の入れ子になったクラスは、外側の構築型ごとに定義されます。Thus, a distinct nested class is defined for each constructed outer type. たとえば、次の宣言があるとします。For example, in the declaration,

// generic_classes_5.cpp
// compile with: /clr /c
generic <typename ItemType>
ref struct Outer {
   ref class Inner {};
};

Outer<int>::Inner 型は、Outer<double>::Inner 型と同じではありません。The type Outer<int>::Inner is not the same as the type Outer<double>::Inner.

ジェネリック クラスのジェネリック メソッドと同様、入れ子にされた型に対して、追加の型パラメーターを定義できます。As with generic methods in generic classes, additional type parameters can be defined for the nested type. 内側と外側のクラスで同じ型パラメーター名を使用した場合、内側の型パラメーターによって外側の型パラメーターが隠されます。If you use the same type parameter names in the inner and outer class, the inner type parameter will hide the outer type parameter.

// generic_classes_6.cpp
// compile with: /clr /c
generic <typename ItemType>
ref class Outer {
   ItemType outer_item;   // refers to outer ItemType

   generic <typename ItemType>
   ref class Inner {
      ItemType inner_item;   // refers to Inner ItemType
   };
};

外側の型パラメーターを参照する手段がないため、このような状況では、コンパイラによって警告が生成されます。Since there is no way to refer to the outer type parameter, the compiler will produce a warning in this situation.

入れ子になったジェネリック構築型に名前がある場合、内側の型が外側の型の型パラメーターによって暗黙的にパラメーター化されるにもかかわらず、外側の型の型パラメーターは内側の型の型パラメーターの一覧に含まれることはありません。When constructed nested generic types are named, the type parameter for the outer type is not included in the type parameter list for the inner type, even though the inner type is implicitly parameterized by the outer type's type parameter. 上記の場合、構築型の名前は、Outer<int>::Inner<string> になります。In the above case, a name of a constructed type would be Outer<int>::Inner<string>.

例: ビルドと読み取りのリンクリストExample: Build and read linked list

次の例では、ジェネリック クラスの入れ子にされた型を使用して、リンクされた一覧をビルドして読み取ることを示します。The following example demonstrates building and reading a linked list using nested types in generic classes.

// generics_linked_list.cpp
// compile with: /clr
using namespace System;
generic <class ItemType>
ref class LinkedList {
// The node class:
public:
   ref class Node {
   // The link field:
   public:
      Node^ next;
      // The data field:
      ItemType item;
   } ^first, ^current;
};

ref class ListBuilder {
public:
   void BuildIt(LinkedList<double>^ list) {
      /* Build the list */
      double m[5] = {0.1, 0.2, 0.3, 0.4, 0.5};
      Console::WriteLine("Building the list:");

      for (int n=0; n<=4; n++) {
         // Create a new node:
         list->current = gcnew LinkedList<double>::Node();

         // Assign a value to the data field:
         list->current->item = m[n];

         // Set the link field "next" to be the same as
         // the "first" field:
         list->current->next = list->first;

         // Redirect "first" to the new node:
         list->first = list->current;

         // Display node's data as it builds:
         Console::WriteLine(list->current->item);
      }
   }

   void ReadIt(LinkedList<double>^ list) {
      // Read the list
      // Make "first" the "current" link field:
      list->current = list->first;
      Console::WriteLine("Reading nodes:");

      // Read nodes until current == null:
      while (list->current != nullptr) {
         // Display the node's data field:
         Console::WriteLine(list->current->item);

         // Move to the next node:
         list->current = list->current->next;
      }
   }
};

int main() {
   // Create a list:
   LinkedList<double>^ aList = gcnew LinkedList<double>();

   // Initialize first node:
   aList->first = nullptr;

   // Instantiate the class, build, and read the list:
   ListBuilder^ myListBuilder = gcnew ListBuilder();
   myListBuilder->BuildIt(aList);
   myListBuilder->ReadIt(aList);
}
Building the list:
0.1
0.2
0.3
0.4
0.5
Reading nodes:
0.5
0.4
0.3
0.2
0.1

ジェネリック クラスのプロパティ、イベント、インデクサー、および演算子Properties, Events, Indexers and Operators in Generic Classes

  • プロパティ、イベント、インデクサー、および演算子では、ItemType がクラスの型パラメーターである場合などに、外側のジェネリック クラスの型パラメーターを、戻り値、パラメーター、またはローカル変数として使用できます。Properties, events, indexers and operators can use the type parameters of the enclosing generic class as return values, parameters, or local variables, such as when ItemType is a type parameter of a class:

    public ItemType MyProperty {}
    
  • プロパティ、イベント、インデクサー、おおび演算子そのものをパラメーター化することはできません。Properties, events, indexers and operators cannot themselves be parameterized.

例: instance プロパティの宣言Example: Declare instance property

この例では、ジェネリック クラス内のインスタンス プロパティの宣言を示します。This example shows declarations of an instance property within a generic class.

// generics_generic_properties1.cpp
// compile with: /clr
using namespace System;

generic <typename ItemType>
ref class MyClass {
private:
   property ItemType myField;

public:
   property ItemType MyProperty {
      ItemType get() {
         return myField;
      }
      void set(ItemType value) {
         myField = value;
      }
   }
};

int main() {
   MyClass<String^>^ c = gcnew MyClass<String^>();
   MyClass<int>^ c1 = gcnew MyClass<int>();

   c->MyProperty = "John";
   c1->MyProperty = 234;

   Console::Write("{0}, {1}", c->MyProperty, c1->MyProperty);
}
John, 234

例: イベントのあるジェネリッククラスExample: Generic class with event

次の例では、イベントを持つジェネリック クラスを示します。The next example shows a generic class with an event.

// generics_generic_with_event.cpp
// compile with: /clr
// Declare a generic class with an event and
// invoke events.
using namespace System;

// declare delegates
generic <typename ItemType>
delegate void ClickEventHandler(ItemType);

// generic class that defines events
generic <typename ItemType>
ref class EventSource {
public:
   // declare the event OnClick
   event ClickEventHandler<ItemType>^ OnClick;
   void FireEvents(ItemType item) {
      // raises events
      OnClick(item);
   }
};

// generic class that defines methods that will called when
// event occurs
generic <typename ItemType>
ref class EventReceiver {
public:
   void OnMyClick(ItemType item) {
   Console::WriteLine("OnClick: {0}", item);
   }
};

int main() {
   EventSource<String^>^ MyEventSourceString =
                   gcnew EventSource<String^>();
   EventSource<int>^ MyEventSourceInt = gcnew EventSource<int>();
   EventReceiver<String^>^ MyEventReceiverString =
                   gcnew EventReceiver<String^>();
   EventReceiver<int>^ MyEventReceiverInt = gcnew EventReceiver<int>();

   // hook handler to event
   MyEventSourceString->OnClick += gcnew ClickEventHandler<String^>(
       MyEventReceiverString, &EventReceiver<String^>::OnMyClick);
   MyEventSourceInt->OnClick += gcnew ClickEventHandler<int>(
             MyEventReceiverInt, &EventReceiver<int>::OnMyClick);

   // invoke events
   MyEventSourceString->FireEvents("Hello");
   MyEventSourceInt->FireEvents(112);

   // unhook handler to event
   MyEventSourceString->OnClick -= gcnew ClickEventHandler<String^>(
        MyEventReceiverString, &EventReceiver<String^>::OnMyClick);
   MyEventSourceInt->OnClick -= gcnew ClickEventHandler<int>(
        MyEventReceiverInt, &EventReceiver<int>::OnMyClick);
}

ジェネリック構造体Generic Structs

ジェネリック構造体を宣言して使用するためのルールは、Visual C++ 言語リファレンスに記載されている違いを除いて、ジェネリック クラスのルールと同じです。The rules for declaring and using generic structs are the same as those for generic classes, except for the differences noted in the Visual C++ language reference.

例: ジェネリック構造体を宣言するExample: Declare generic struct

次の例では、1つのフィールドを持つジェネリック構造体を宣言 MyGenStruct myField し、別の型 ( int 、、) の値を double String^ このフィールドに代入します。The following example declares a generic struct, MyGenStruct, with one field, myField, and assigns values of different types (int, double, String^) to this field.

// generics_generic_struct1.cpp
// compile with: /clr
using namespace System;

generic <typename ItemType>
ref struct MyGenStruct {
public:
   ItemType myField;

   ItemType AssignValue(ItemType item) {
      myField = item;
      return myField;
   }
};

int main() {
   int myInt = 123;
   MyGenStruct<int>^ myIntObj = gcnew MyGenStruct<int>();
   myIntObj->AssignValue(myInt);
   Console::WriteLine("The field is assigned the integer value: {0}",
            myIntObj->myField);

   double myDouble = 0.123;
   MyGenStruct<double>^ myDoubleObj = gcnew MyGenStruct<double>();
   myDoubleObj->AssignValue(myDouble);
   Console::WriteLine("The field is assigned the double value: {0}",
            myDoubleObj->myField);

   String^ myString = "Hello Generics!";
   MyGenStruct<String^>^ myStringObj = gcnew MyGenStruct<String^>();
   myStringObj->AssignValue(myString);
   Console::WriteLine("The field is assigned the string: {0}",
            myStringObj->myField);
}
The field is assigned the integer value: 123
The field is assigned the double value: 0.123
The field is assigned the string: Hello Generics!

関連項目See also

ジェネリックGenerics