Maison >développement back-end >Tutoriel C#.Net >Introduction graphique et textuelle détaillée aux contraintes de type Where en C#

Introduction graphique et textuelle détaillée aux contraintes de type Where en C#

黄舟
黄舟original
2017-03-03 13:17:471362parcourir

Contraintes sur les paramètres de type (Guide de programmation C#)

Visual Studio 2005





Autres versions

Lors de la définition d'une classe générique, vous pouvez Impose des restrictions sur les types de types que le code client peut utiliser pour les paramètres de type lors de l'instanciation d'une classe. Si le code client tente d'instancier une classe à l'aide d'un type non autorisé par une contrainte, une erreur de compilation se produit. Ces limites sont appelées contraintes. Les contraintes sont spécifiées à l'aide du mot-clé contextuel where. Le tableau suivant répertorie les six types de contraintes :

Contraintes Description

T : Les paramètres de type Structure

doivent être des types valeur. Tout type de valeur, à l'exception de Nullable, peut être spécifié. Pour plus d’informations, consultez Utilisation de types nullables (C# Guide de programmation).

T : Classe

Les paramètres de type doivent être des types de référence, y compris n'importe quel type de classe, d'interface, de délégué ou de tableau.

T: new()

les paramètres de type doivent avoir un constructeur public sans paramètre. Lorsqu'elle est utilisée avec d'autres contraintes, la contrainte new() doit être spécifiée en dernier.

T : 399ab3de591e39d5c58a42e4aed9ec6c

Le paramètre de type doit être la classe de base spécifiée ou dérivé de La classe de base spécifiée.

T : 5def63e93e161f3e64b46270624ddb26

Le paramètre type doit être l'interface spécifiée ou implémenter l'interface spécifiée. Plusieurs contraintes d'interface peuvent être spécifiées. Les interfaces de contraintes peuvent également être génériques.

T : U

Les paramètres de type fournis pour T doivent être des paramètres fournis pour U ou dérivés des paramètres U fournis . C'est ce qu'on appelle une contrainte de type nu.


Raisons d'utiliser des contraintes


Si vous souhaitez vérifier un élément dans une liste générique pour voir s'il est valide, ou le comparer à un autre élément Pour effectuer une comparaison, le compilateur doit fournir une certaine assurance que l'opérateur ou la méthode qu'il doit appeler sera pris en charge par tous les paramètres de type que le code client peut spécifier. Cette garantie est obtenue en appliquant une ou plusieurs contraintes à la définition de la classe générique. Par exemple, une contrainte de classe de base indique au compilateur que seuls les objets de ce type ou les objets dérivés de ce type peuvent être utilisés comme paramètres de type. Une fois que le compilateur dispose de cette garantie, il peut autoriser l’appel de méthodes de ce type dans une classe générique. Les contraintes sont appliquées à l'aide du mot-clé contextuel where . L'exemple de code suivant montre comment ajouter des contraintes de classe de base à la classe GenericList8742468051c85b06f0a0af9e3e506b5c (dans Introduction aux génériques (C# Guide de programmation)).

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

Avec les paramètres de type de contrainte, vous pouvez augmenter le nombre d'opérations autorisées et d'appels de méthodes pris en charge par le type de contrainte et tous les types de sa hiérarchie d'héritage. Par conséquent, lors de la conception d'une classe ou d'une méthode générique, si vous souhaitez faire autre chose qu'une simple affectation à un membre générique ou appeler une méthode qui n'est pas prise en charge par System.Object , vous aurez besoin du paramètre de type Apply contraintes.

Lors de l'application de la contrainte where T : class, il est recommandé de ne pas utiliser les opérateurs == et != pour paramètres de type. Parce que ces opérateurs testent uniquement l’identité de référence et non l’égalité de valeur. Ceci est vrai même si ces opérateurs sont surchargés dans le type utilisé en paramètre. Le code ci-dessous illustre cela ; même si la classe String surcharge l'opérateur ==, le résultat est FAUX.

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

La raison en est que le compilateur ne sait qu'au moment de la compilation que T est un type référence, il doit donc utiliser l'opérateur par défaut qui est valide pour tous les types référence . Si vous devez tester l'égalité des valeurs, l'approche recommandée consiste à la fois à appliquer la contrainte where T : IComparable8742468051c85b06f0a0af9e3e506b5c et à implémenter l'interface dans n'importe quelle classe qui sera utilisée pour construire la classe générique.

Paramètre de type non lié



Paramètre de type non lié (tel que la classe publique SampleClass< Le T dans T> ;{}) est appelé un paramètre de type non lié. Les paramètres de type non liés ont les règles suivantes :

  • ne peut pas être utilisé avec les opérateurs != et == car il n'y a aucune garantie de béton paramètres de type Ces opérateurs sont pris en charge.

  • peut être converti entre eux et System.Object ou explicitement converti en n'importe quel type d'interface.

  • peut être comparé à null . Lors de la comparaison d'un paramètre indépendant à null , la comparaison renverra toujours false si le paramètre de type est un type valeur.

Contraintes de type nu



Les paramètres de type génériques utilisés comme contraintes sont appelés contraintes de type nu . Les contraintes de type nu sont utiles lorsqu'une fonction membre qui possède son propre paramètre de type doit contraindre ce paramètre à un paramètre de type du type conteneur, comme dans l'exemple suivant :

C#

class List<T>
{
    void Add<U>(List<U> items) where U : T {/*...*/}
}

Dans l'exemple ci-dessus, T est une contrainte de type nu dans le contexte de la méthode Add, et est une contrainte de type nu dans le contexte de la List paramètre de type non lié de classe.

Les contraintes de type nu peuvent également être utilisées dans les définitions de classes génériques. Notez que la contrainte de type nu doit également avoir été déclarée entre crochets avec tout autre paramètre de type :

C#
//naked type constraint
public class SampleClass<T, U, V> where T : V { }

Le rôle d'une contrainte de type nu sur une classe générique est très limité, car le compilateur ne suppose rien plus d'une certaine contrainte de type nue ne fait aucune hypothèse autre que celle d'être dérivée de System.Object . Vous pouvez utiliser des contraintes de type nu sur une classe générique lorsque vous souhaitez appliquer une relation d'héritage entre deux paramètres de type.

Ce qui précède contient les détails graphiques et textuels des contraintes de type Where en C#. Pour plus de contenu connexe, veuillez faire attention au site Web PHP chinois (www.php.cn) !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn