Aracılığıyla paylaş


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> 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, SortedList<T> sınıfından türetilen bir GenericList<T> sınıfını gösterir. Daha fazla bilgi için bkz. Genel Türlere Giriş. SortedList<T> kısıtlamasını where T : IComparable<T>ekler. Bu kısıtlama, BubbleSort içindeki SortedList<T> yönteminin liste öğelerinde genel CompareTo yöntemini 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 arabirimler genel olmayan arabirimlerden devralabilir. .NET sınıf kitaplığında, IEnumerable<T> öğesinden IEnumerabledevralır. Genel arabirim, genel olmayan bir arabirimden devraldığında, tür parametresi genellikle geçersiz kılınan üyelerde object yerine geçer. Örneğin, IEnumerable<T>, T'ün dönüş değeri ve object özelliği alıcı kısmında GetEnumerator yerine Current kullanır. Yalnızca T bu üyelerin çıkış konumlarında kullanıldığından, IEnumerable<T> birlikte değişken olarak işaretlenebilir. Geçersiz kılınmış bir üyede giriş konumunda kullanıldıysa T , arabirim birlikte değişken olamaz ve derleyici bir hata oluşturur.

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.

Arabirimler static abstract veya static virtual üyelerini tanımlayabilir. static abstract veya static virtual üyelerini bildiren arabirimler neredeyse her zaman genel arabirimlerdir. Derleyicinin derleme zamanında ve static virtual yöntemlerine static abstract yapılan çağrıları çözümlemesi gerekir. static virtual ve static abstract arabirimlerde bildirilen yöntemlerin, sınıflarda bildirilen virtual veya abstract yöntemlerine 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 arabirimistatic abstract bildirir. Derleyici daha sonra bildirilen üyenin türünü çözümlemek için sağlanan tür argümanlarını kullanır.

Ayrıca bakınız