Ograniczenia dotyczące parametrów typu ogólnego (C++/CLI)

W deklaracjach typów ogólnych lub metod można zakwalifikować parametr typu z ograniczeniami. Ograniczenie jest wymaganiem, które typy używane jako argumenty typu muszą spełniać. Na przykład ograniczeniem może być to, że argument typu musi zaimplementować określony interfejs lub dziedziczyć z określonej klasy.

Ograniczenia są opcjonalne; nie określa ograniczenia dla parametru jest równoważne użyciu Object ograniczenia.

Składnia

where type-parameter : constraint-list

Parametry

type-parameter
Jeden z identyfikatorów parametrów typu do ograniczenia.

constraint-list
Rozdzielona przecinkami lista specyfikacji ograniczeń. Lista może zawierać interfejsy, które mają być implementowane przez element type-parameter.

Lista może również zawierać klasę. Aby spełnić ograniczenie klasy bazowej, argument typu musi być tą samą klasą co ograniczenie lub pochodzić z ograniczenia. Określ ref class , aby wskazać, że argument typu musi być typem odwołania, w tym dowolnym classtypem , interface, delegatelub array . Określ, value class aby wskazać argument typu musi być typem wartości. Dowolny typ wartości z wyjątkiem Nullable<T> można określić.

Można również określić, aby wskazać gcnew() , że argument typu musi mieć publiczny konstruktor bez parametrów.

Można również określić parametr ogólny jako ograniczenie. Argument typu podany dla typu, który ograniczasz, musi być lub pochodzić z typu ograniczenia. Ten parametr jest nazywany ograniczeniem typu naked.

Uwagi

Klauzula ograniczenia składa się z parametru where typu, dwukropka (:) i ograniczenia określającego charakter ograniczenia dla parametru typu. where jest kontekstowym słowem kluczowym. Aby uzyskać więcej informacji, zobacz Kontekstowe słowa kluczowe. Oddzielaj wiele where klauzul spacją.

Ograniczenia są stosowane do parametrów typu w celu umieszczenia ograniczeń dotyczących typów, które mogą być używane jako argumenty dla typu ogólnego lub metody.

Ograniczenia klasy i interfejsu określają, że typy argumentów muszą być lub dziedziczyć z określonej klasy lub zaimplementować określony interfejs.

Zastosowanie ograniczeń do typu ogólnego lub metody umożliwia kodowi w tym typie lub metodzie korzystanie ze znanych funkcji typów ograniczonych. Można na przykład zadeklarować klasę ogólną, tak aby parametr type implementuje IComparable<T> interfejs:

// generics_constraints_1.cpp
// compile with: /c /clr
using namespace System;
generic <typename T>
where T : IComparable<T>
ref class List {};

To ograniczenie wymaga, aby argument typu używany do T implementowania IComparable<T> w czasie kompilacji. Umożliwia również wywoływanie metod interfejsu, takich jak CompareTo, . W wystąpieniu parametru typu nie jest wymagane rzutowanie, aby wywołać metody interfejsu.

Metody statyczne w klasie argumentu typu nie mogą być wywoływane za pomocą parametru typu; mogą być wywoływane tylko za pośrednictwem rzeczywistego nazwanego typu.

Ograniczenie nie może być typem wartości, w tym wbudowanymi typami, takimi jak int lub double. Ponieważ typy wartości nie mogą mieć klas pochodnych, tylko jedna klasa może kiedykolwiek spełnić ograniczenie. W takim przypadku rodzaj może zostać przepisany za pomocą parametru typu zastąpionego określonym typem wartości.

Ograniczenia są wymagane w niektórych przypadkach, ponieważ kompilator nie zezwoli na używanie metod lub innych funkcji nieznanego typu, chyba że ograniczenia oznaczają, że nieznany typ obsługuje metody lub interfejsy.

Na liście rozdzielanej przecinkami można określić wiele ograniczeń dla tego samego parametru typu

// generics_constraints_2.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;
generic <typename T>
where T : List<T>, IComparable<T>
ref class List {};

W przypadku wielu parametrów typu należy użyć klauzuli where dla każdego parametru typu. Przykład:

// generics_constraints_3.cpp
// compile with: /c /clr
using namespace System;
using namespace System::Collections::Generic;

generic <typename K, typename V>
   where K: IComparable<K>
   where V: IComparable<K>
ref class Dictionary {};

Użyj ograniczeń w kodzie zgodnie z następującymi regułami:

  • Jeśli na liście znajduje się wiele ograniczeń, ograniczenia mogą być wymienione w dowolnej kolejności.

  • Ograniczenia mogą być również typami klas, takimi jak abstrakcyjne klasy bazowe. Jednak ograniczenia nie mogą być typami wartości ani sealed klasami.

  • Ograniczenia nie mogą być parametrami typu, ale mogą obejmować parametry typu w otwartym skonstruowanym typie. Przykład:

    // generics_constraints_4.cpp
    // compile with: /c /clr
    generic <typename T>
    ref class G1 {};
    
    generic <typename Type1, typename Type2>
    where Type1 : G1<Type2>   // OK, G1 takes one type parameter
    ref class G2{};
    

Przykłady

W poniższym przykładzie pokazano używanie ograniczeń do wywoływania metod wystąpień w parametrach typu.

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

interface class IAge {
   int Age();
};

ref class MyClass {
public:
   generic <class ItemType> where ItemType : IAge
   bool isSenior(ItemType item) {
      // Because of the constraint,
      // the Age method can be called on ItemType.
      if (item->Age() >= 65)
         return true;
      else
         return false;
   }
};

ref class Senior : IAge {
public:
   virtual int Age() {
      return 70;
   }
};

ref class Adult: IAge {
public:
   virtual int Age() {
      return 30;
   }
};

int main() {
   MyClass^ ageGuess = gcnew MyClass();
   Adult^ parent = gcnew Adult();
   Senior^ grandfather = gcnew Senior();

   if (ageGuess->isSenior<Adult^>(parent))
      Console::WriteLine("\"parent\" is a senior");
   else
      Console::WriteLine("\"parent\" is not a senior");

   if (ageGuess->isSenior<Senior^>(grandfather))
      Console::WriteLine("\"grandfather\" is a senior");
   else
      Console::WriteLine("\"grandfather\" is not a senior");
}
"parent" is not a senior
"grandfather" is a senior

Gdy parametr typu ogólnego jest używany jako ograniczenie, jest nazywany ograniczeniem typu nagiego. Ograniczenia typu naked są przydatne, gdy funkcja składowa z własnym parametrem typu musi ograniczyć ten parametr do parametru typu zawierającego typ.

W poniższym przykładzie T jest ograniczeniem typu naked w kontekście Add metody .

Ograniczenia typu naked mogą być również używane w definicjach klas ogólnych. Użyteczność ograniczeń typu nagiego z klasami ogólnymi jest ograniczona, ponieważ kompilator nie może założyć nic o ograniczeniu typu nagiego z wyjątkiem tego, że pochodzi z Objectklasy . Używaj ograniczeń typu naked dla klas ogólnych w scenariuszach, w których chcesz wymusić relację dziedziczenia między dwoma parametrami typu.

// generics_constraints_6.cpp
// compile with: /clr /c
generic <class T>
ref struct List {
   generic <class U>
   where U : T
   void Add(List<U> items)  {}
};

generic <class A, class B, class C>
where A : C
ref struct SampleClass {};

Zobacz też

Typy ogólne