Allmänna klasser och metoder

Generics introducerar begreppet typparametrar för .NET. Generiska objekt gör det möjligt att utforma klasser och metoder som skjuter upp specifikationen för en eller flera typparametrar tills du använder klassen eller metoden i koden. Genom att till exempel använda en generisk typparameter Tkan du skriva en enda klass som annan klientkod kan använda utan att medföra kostnaden eller risken för körningsgjutningar eller boxningsåtgärder, som du ser här:

// Declare the generic class.
public class GenericList<T>
{
    public void Add(T input) { }
}
class TestGenericList
{
    private class ExampleClass { }
    static void Main()
    {
        // Declare a list of type int.
        GenericList<int> list1 = new GenericList<int>();
        list1.Add(1);

        // Declare a list of type string.
        GenericList<string> list2 = new GenericList<string>();
        list2.Add("");

        // Declare a list of type ExampleClass.
        GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
        list3.Add(new ExampleClass());
    }
}

Generiska klasser och metoder kombinerar återanvändbarhet, typsäkerhet och effektivitet på ett sätt som deras icke-generiska motsvarigheter inte kan. Generiska typparametrar ersätts med typargumenten under kompilering. I föregående exempel ersätter T kompilatorn med int. Generiska program används oftast med samlingar och de metoder som fungerar på dem. Namnområdet System.Collections.Generic innehåller flera generiska samlingsklasser. Icke-generiska samlingar, till exempel ArrayList rekommenderas inte och underhålls endast i kompatibilitetssyfte. Mer information finns i Generiska objekt i .NET.

Du kan också skapa anpassade generiska typer och metoder för att tillhandahålla egna generaliserade lösningar och designmönster som är typsäkra och effektiva. I följande kodexempel visas en enkel allmän länkad listklass i demonstrationssyfte. (I de flesta fall bör du använda klassen List<T> som tillhandahålls av .NET i stället för att skapa din egen.) Typparametern T används på flera platser där en betongtyp vanligtvis används för att ange vilken typ av objekt som lagras i listan:

  • Som typ av en metodparameter i AddHead metoden.
  • Som returtyp för Data egenskapen i den kapslade Node klassen.
  • Som typen av privat medlem data i den kapslade klassen.

T är tillgänglig för den kapslade Node klassen. När GenericList<T> instansieras med en betongtyp, till exempel som en GenericList<int>, ersätts varje förekomst av T med int.

// type parameter T in angle brackets
public class GenericList<T>
{
    // The nested class is also generic on T.
    private class Node
    {
        // T used in non-generic constructor.
        public Node(T t)
        {
            next = null;
            data = t;
        }

        private Node? next;
        public Node? Next
        {
            get { return next; }
            set { next = value; }
        }

        // T as private member data type.
        private T data;

        // T as return type of property.
        public T Data
        {
            get { return data; }
            set { data = value; }
        }
    }

    private Node? head;

    // constructor
    public GenericList()
    {
        head = null;
    }

    // T as method parameter type:
    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;
        }
    }
}

I följande kodexempel visas hur klientkoden använder den generiska GenericList<T> klassen för att skapa en lista med heltal. Om du ändrar typargumentet skapar följande kod listor med strängar eller någon annan anpassad typ:

class TestGenericList
{
    static void Main()
    {
        // int is the type argument
        GenericList<int> list = new GenericList<int>();

        for (int x = 0; x < 10; x++)
        {
            list.AddHead(x);
        }

        foreach (int i in list)
        {
            System.Console.Write(i + " ");
        }
        System.Console.WriteLine("\nDone");
    }
}

Kommentar

Generiska typer är inte begränsade till klasser. I föregående exempel används class typer, men du kan definiera generiska interface typer och struct typer, inklusive record typer.

Översikt över generiska data

  • Använd allmänna typer för att maximera återanvändning av kod, typsäkerhet och prestanda.
  • Den vanligaste användningen av generiska läkemedel är att skapa samlingsklasser.
  • .NET-klassbiblioteket innehåller flera generiska samlingsklasser i System.Collections.Generic namnområdet. De generiska samlingarna ska användas när det är möjligt i stället för klasser som ArrayList i System.Collections namnområdet.
  • Du kan skapa egna allmänna gränssnitt, klasser, metoder, händelser och ombud.
  • Allmänna klasser kan begränsas för att ge åtkomst till metoder för vissa datatyper.
  • Du kan hämta information vid körning om de typer som används i en allmän datatyp med hjälp av reflektion.

Språkspecifikation för C#

Mer information finns i C#-språkspecifikationen.

Se även