Heim > Artikel > Backend-Entwicklung > Detaillierte Grafik- und Texteinführung zu Where-Typ-Einschränkungen in C#
Einschränkungen für Typparameter (C#-Programmierhandbuch)
Visual Studio 2005
Andere Versionen
Beim Definieren einer generischen Klasse können Sie dies tun Legt Beschränkungen für die Arten von Typen fest, die Clientcode beim Instanziieren einer Klasse als Typparameter verwenden kann. Wenn Clientcode versucht, eine Klasse mithilfe eines Typs zu instanziieren, der durch eine Einschränkung nicht zulässig ist, tritt ein Fehler bei der Kompilierung auf. Diese Grenzen werden als Einschränkungen bezeichnet. Einschränkungen werden mit dem Kontextschlüsselwort where angegeben. In der folgenden Tabelle sind die sechs Arten von Einschränkungen aufgeführt:
Einschränkungen | Beschreibung |
---|---|
T : Struktur |
Typparameter müssen Werttypen sein. Es kann jeder Werttyp außer Nullable angegeben werden. Weitere Informationen finden Sie unter Verwenden von Nullable-Typen (C#). Programmierhandbuch). |
T: Klasse |
Typparameter müssen Referenztypen sein, einschließlich aller Klassen, Schnittstellen, Delegaten oder Array-Typen. |
T: new() |
Typparameter müssen einen parameterlosen öffentlichen Konstruktor haben. Bei Verwendung mit anderen Einschränkungen muss die Einschränkung new() zuletzt angegeben werden. |
T: 3acc9008e81f2eee0508b69b99bba336 |
Der Typparameter muss die angegebene Basisklasse sein oder von dieser abgeleitet sein Die angegebene Basisklasse. |
T: 1ae1521b56d1270bb3f826e6d94e6d85 |
Der Typparameter muss die angegebene Schnittstelle sein oder die angegebene Schnittstelle implementieren. Es können mehrere Schnittstellenbeschränkungen angegeben werden. Constraint-Schnittstellen können auch generisch sein. |
T: U |
Für T bereitgestellte Typparameter müssen für U bereitgestellte Parameter sein oder von bereitgestellten U-Parametern abgeleitet werden . Dies wird als nackte Typbeschränkung bezeichnet. |
Gründe für die Verwendung von Einschränkungen
Wenn Sie ein Element in einer generischen Liste überprüfen möchten, um festzustellen, ob es gültig ist, oder es mit einem anderen Element vergleichen möchten Um einen Vergleich durchzuführen, muss der Compiler eine gewisse Sicherheit bieten, dass der Operator oder die Methode, die er aufrufen muss, von allen Typparametern unterstützt wird, die der Clientcode möglicherweise angibt. Diese Garantie wird durch die Anwendung einer oder mehrerer Einschränkungen auf die generische Klassendefinition erreicht. Beispielsweise teilt eine Basisklasseneinschränkung dem Compiler mit, dass nur Objekte dieses Typs oder von diesem Typ abgeleitete Objekte als Typparameter verwendet werden können. Sobald der Compiler über diese Garantie verfügt, kann er den Aufruf von Methoden dieses Typs in einer generischen Klasse zulassen. Einschränkungen werden mithilfe des Kontextschlüsselworts where angewendet. Das folgende Codebeispiel zeigt, wie Basisklasseneinschränkungen zur Klasse GenericList8742468051c85b06f0a0af9e3e506b5c hinzugefügt werden (in Einführung in Generics (C#). Programmieranleitung)).
public class Employee { private string name; private int id; public Employee(string s, int i) { name = s; id = i; } public string Name { get { return name; } set { name = value; } } public int ID { get { return id; } set { id = value; } } } public class GenericList<T> where T : Employee { private class Node { private Node next; private T data; public Node(T t) { next = null; data = t; } public Node Next { get { return next; } set { next = value; } } public T Data { get { return data; } set { data = value; } } } private Node head; public GenericList() //constructor { head = null; } public void AddHead(T t) { Node n = new Node(t); n.Next = head; head = n; } public IEnumerator<T> GetEnumerator() { Node current = head; while (current != null) { yield return current.Data; current = current.Next; } } public T FindFirstOccurrence(string s) { Node current = head; T t = null; while (current != null) { //The constraint enables access to the Name property. if (current.Data.Name == s) { t = current.Data; break; } else { current = current.Next; } } return t; } }
Mit Einschränkungstypparametern können Sie die Anzahl der zulässigen Operationen und Methodenaufrufe erhöhen, die vom Einschränkungstyp und allen Typen in seiner Vererbungshierarchie unterstützt werden. Wenn Sie daher beim Entwerfen einer generischen Klasse oder Methode etwas anderes als eine einfache Zuweisung zu einem generischen Mitglied durchführen oder eine Methode aufrufen möchten, die nicht von System.Object unterstützt wird, benötigen Sie den Typparameter Apply Einschränkungen.
Bei Anwendung der Einschränkung where T : class wird empfohlen, die Operatoren == und != nicht zu verwenden Typparameter, da diese Operatoren nur die Referenzidentität und nicht die Wertegleichheit testen. Dies gilt auch dann, wenn diese Operatoren in dem als Parameter verwendeten Typ überladen sind. Der folgende Code veranschaulicht dies; obwohl die String-Klasse den Operator == überlädt, ist die Ausgabe FALSCH.
C#
public static void OpTest<T>(T s, T t) where T : class { System.Console.WriteLine(s == t); } static void Main() { string s1 = "foo"; System.Text.StringBuilder sb = new System.Text.StringBuilder("foo"); string s2 = sb.ToString(); OpTest<string>(s1, s2); }
Der Grund dafür ist, dass der Compiler erst zur Kompilierungszeit weiß, dass T ein Referenztyp ist, also muss er den Standardoperator verwenden, der für alle Referenztypen gültig ist . Wenn Sie die Wertegleichheit testen müssen, besteht der empfohlene Ansatz darin, sowohl die Einschränkung where T : IComparable8742468051c85b06f0a0af9e3e506b5c anzuwenden als auch die Schnittstelle in jeder Klasse zu implementieren, die zum Erstellen der generischen Klasse verwendet wird.
Ungebundener Typparameter
Ungebundener Typparameter (z. B. öffentliche Klasse SampleClass< Das T in T> ;{}) wird als ungebundener Typparameter bezeichnet. Für ungebundene Typparameter gelten die folgenden Regeln:
kann nicht mit den Operatoren != und == verwendet werden, da es keine Garantie für Konkretheit gibt Typparameter Diese Operatoren werden unterstützt.
kann zwischen ihnen und System.Object hin und her konvertiert oder explizit in einen beliebigen Schnittstellentyp konvertiert werden.
kann mit null verglichen werden. Beim Vergleich eines ungebundenen Parameters mit null gibt der Vergleich immer false zurück, wenn der Typparameter ein Werttyp ist.
Naked-Type-Einschränkungen
Generische Typparameter, die als Einschränkungen verwendet werden, werden als Naked-Type-Einschränkungen bezeichnet . Nackte Typeinschränkungen sind nützlich, wenn eine Memberfunktion, die über einen eigenen Typparameter verfügt, diesen Parameter auf einen Typparameter des enthaltenden Typs beschränken muss, wie im folgenden Beispiel:
C#
class List<T> { void Add<U>(List<U> items) where U : T {/*...*/} }
Im obigen Beispiel ist T eine nackte Typbeschränkung im Kontext der Add-Methode und eine nackte Typbeschränkung im Kontext der List Klasse Ungebundener Typparameter.
Naked-Type-Einschränkungen können auch in generischen Klassendefinitionen verwendet werden. Beachten Sie, dass die nackte Typbeschränkung zusammen mit allen anderen Typparametern auch in spitzen Klammern deklariert worden sein muss:
C# //naked type constraint public class SampleClass<T, U, V> where T : V { }
Die Rolle einer nackten Typbeschränkung für eine generische Klasse ist sehr begrenzt, da der Compiler nichts voraussetzt Mehr als eine bestimmte nackte Typeinschränkung treffen keine anderen Annahmen als die, die von System.Object abgeleitet werden. Sie können nackte Typeinschränkungen für eine generische Klasse verwenden, wenn Sie eine Vererbungsbeziehung zwischen zwei Typparametern erzwingen möchten.
Oben finden Sie die grafischen und textlichen Details zu Typbeschränkungen in C#. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (www.php.cn).