Genel Arabirimler (C# Programlama Kılavuzu)

Genellikle genel koleksiyon sınıfları veya koleksiyondaki öğeleri temsil eden genel sınıflar için arabirimler tanımlamak yararlı olur. Değer türlerinde kutulama ve kutu açma işlemlerini önlemek için, genel sınıflarda gibi IComparable<T>genel arabirimleri kullanmak daha iyidir. .NET sınıf kitaplığı, ad alanında System.Collections.Generic koleksiyon sınıfları ile kullanılmak üzere çeşitli genel arabirimler tanımlar. Bu arabirimler hakkında daha fazla bilgi için bkz . Genel arabirimler.

Bir arabirim tür parametresinde kısıtlama olarak belirtildiğinde, yalnızca arabirimi uygulayan türler kullanılabilir. Aşağıdaki kod örneği, sınıfından türetilen GenericList<T> bir SortedList<T> sınıfı gösterir. Daha fazla bilgi için bkz . Genel Kullanıma Giriş. SortedList<T> kısıtlamasını where T : IComparable<T>ekler. Bu kısıtlama, içindeki yönteminin BubbleSortSortedList<T> liste öğelerinde genel CompareTo yöntemi kullanmasını sağlar. Bu örnekte, liste öğeleri uygulayan basit bir sınıftır PersonIComparable<Person>.

//Type parameter T in angle brackets.
public class GenericList<T> : System.Collections.Generic.IEnumerable<T>
{
    protected Node head;
    protected Node current = null;

    // Nested class is also generic on T
    protected class Node
    {
        public Node next;
        private T data;  //T as private member datatype

        public Node(T t)  //T used in non-generic constructor
        {
            next = null;
            data = t;
        }

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

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

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

    public void AddHead(T t)  //T as method parameter type
    {
        Node n = new Node(t);
        n.Next = head;
        head = n;
    }

    // Implementation of the iterator
    public System.Collections.Generic.IEnumerator<T> GetEnumerator()
    {
        Node current = head;
        while (current != null)
        {
            yield return current.Data;
            current = current.Next;
        }
    }

    // IEnumerable<T> inherits from IEnumerable, therefore this class
    // must implement both the generic and non-generic versions of
    // GetEnumerator. In most cases, the non-generic method can
    // simply call the generic method.
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public class SortedList<T> : GenericList<T> where T : System.IComparable<T>
{
    // A simple, unoptimized sort algorithm that
    // orders list elements from lowest to highest:

    public void BubbleSort()
    {
        if (null == head || null == head.Next)
        {
            return;
        }
        bool swapped;

        do
        {
            Node previous = null;
            Node current = head;
            swapped = false;

            while (current.next != null)
            {
                //  Because we need to call this method, the SortedList
                //  class is constrained on IComparable<T>
                if (current.Data.CompareTo(current.next.Data) > 0)
                {
                    Node tmp = current.next;
                    current.next = current.next.next;
                    tmp.next = current;

                    if (previous == null)
                    {
                        head = tmp;
                    }
                    else
                    {
                        previous.next = tmp;
                    }
                    previous = tmp;
                    swapped = true;
                }
                else
                {
                    previous = current;
                    current = current.next;
                }
            }
        } while (swapped);
    }
}

// A simple class that implements IComparable<T> using itself as the
// type argument. This is a common design pattern in objects that
// are stored in generic lists.
public class Person : System.IComparable<Person>
{
    string name;
    int age;

    public Person(string s, int i)
    {
        name = s;
        age = i;
    }

    // This will cause list elements to be sorted on age values.
    public int CompareTo(Person p)
    {
        return age - p.age;
    }

    public override string ToString()
    {
        return name + ":" + age;
    }

    // Must implement Equals.
    public bool Equals(Person p)
    {
        return (this.age == p.age);
    }
}

public class Program
{
    public static void Main()
    {
        //Declare and instantiate a new generic SortedList class.
        //Person is the type argument.
        SortedList<Person> list = new SortedList<Person>();

        //Create name and age values to initialize Person objects.
        string[] names =
        [
            "Franscoise",
            "Bill",
            "Li",
            "Sandra",
            "Gunnar",
            "Alok",
            "Hiroyuki",
            "Maria",
            "Alessandro",
            "Raul"
        ];

        int[] ages = [45, 19, 28, 23, 18, 9, 108, 72, 30, 35];

        //Populate the list.
        for (int x = 0; x < 10; x++)
        {
            list.AddHead(new Person(names[x], ages[x]));
        }

        //Print out unsorted list.
        foreach (Person p in list)
        {
            System.Console.WriteLine(p.ToString());
        }
        System.Console.WriteLine("Done with unsorted list");

        //Sort the list.
        list.BubbleSort();

        //Print out sorted list.
        foreach (Person p in list)
        {
            System.Console.WriteLine(p.ToString());
        }
        System.Console.WriteLine("Done with sorted list");
    }
}

Birden çok arabirim, aşağıdaki gibi tek bir türde kısıtlama olarak belirtilebilir:

class Stack<T> where T : System.IComparable<T>, IEnumerable<T>
{
}

Bir arabirim, aşağıdaki gibi birden fazla tür parametresi tanımlayabilir:

interface IDictionary<K, V>
{
}

Sınıflara uygulanan devralma kuralları arabirimler için de geçerlidir:

interface IMonth<T> { }

interface IJanuary : IMonth<int> { }  //No error
interface IFebruary<T> : IMonth<int> { }  //No error
interface IMarch<T> : IMonth<T> { }    //No error
                                       //interface IApril<T>  : IMonth<T, U> {}  //Error

Genel arabirim birlikte değişkense, genel arabirimler genel olmayan arabirimlerden devralabilir, yani yalnızca dönüş değeri olarak kendi tür parametresini kullanır. .NET sınıf kitaplığında, IEnumerable<T> öğesinden IEnumerable devralır çünkü IEnumerable<T> yalnızca ve dönüş değerinde GetEnumerator ve özellik alıcısında Current kullanırT.

Beton sınıflar aşağıdaki gibi kapalı oluşturulan arabirimler uygulayabilir:

interface IBaseInterface<T> { }

class SampleClass : IBaseInterface<string> { }

Sınıf parametre listesi, arabirimin gerektirdiği tüm bağımsız değişkenleri sağladığı sürece genel sınıflar genel arabirimleri veya kapalı oluşturulmuş arabirimleri aşağıdaki gibi uygulayabilir:

interface IBaseInterface1<T> { }
interface IBaseInterface2<T, U> { }

class SampleClass1<T> : IBaseInterface1<T> { }          //No error
class SampleClass2<T> : IBaseInterface2<T, string> { }  //No error

Yöntem aşırı yüklemesini denetleen kurallar, genel sınıflar, genel yapılar veya genel arabirimler içindeki yöntemler için aynıdır. Daha fazla bilgi için bkz . Genel Yöntemler.

C# 11'de başlayarak, arabirimler veya static virtual üyelerini bildirebilirstatic abstract. veya static virtual üyelerini bildiren static abstract arabirimler neredeyse her zaman genel arabirimlerdir. Derleyicinin derleme zamanında ve static abstract yöntemlerine static virtual yapılan çağrıları çözümlemesi gerekir. static virtualve static abstract arabirimlerde bildirilen yöntemlerin sınıflarda bildirilen veya abstract yöntemlerine virtual benzer bir çalışma zamanı dağıtım mekanizması yoktur. Bunun yerine, derleyici derleme zamanında kullanılabilen tür bilgilerini kullanır. Bu üyeler genellikle genel arabirimlerde bildirilir. Ayrıca, veya yöntemlerini bildiren static virtual çoğu arabirim, tür parametrelerinden birinin bildirilen arabirimi uygulaması gerektiğini static abstract bildirir. Derleyici daha sonra bildirilen üyenin türünü çözümlemek için sağlanan tür bağımsız değişkenlerini kullanır.

Ayrıca bkz.