Aracılığıyla paylaş


Genişletme Yöntemleri (C# Programlama Kılavuzu)

Uzantı yöntemleri, yeni türetilmiş bir tür oluşturmadan, yeniden derlemeden ya da özgün türü değiştirmeden yöntemler "eklemenizi" sağlar.Uzantı yöntemleri özel bir statik yöntem türüdür, ancak bunlar genişletilmiş türdeki örnek yöntemler ise çağrılır.C# ve Visual Basic'te yazılmış istemci kodu için, genişletme yöntemini çağırma ile gerçekte bir tür içinde tanımlanan yöntemleri çağırma arasında görünür bir fark yoktur.

En yaygın genişletme yöntemleri varolan IEnumerable ve IEnumerable türlerine sorgu işlevselliği ekleyen LINQ standart sorgu işleçleridir.Standart sorgu işleçleri kullanmak için, önce bunları using System.Linq yönergesiyle kapsama taşıyın.Sonra IEnumerable uygulayan türler GroupBy``2, OrderBy``2, Average vb. örnek yöntemlerine sahip görünür.IntelliSense deyim tamamlamada bu ek yöntemleri, IEnumerable türünün örneğinden sonra (List veya Array) "nokta" yazdığınızda görebilirsiniz.

Aşağıdaki örnek, bir tamsayı dizisinde standart sorgu işleci OrderBy yönteminin nasıl çağrıldığını gösterir.Parantez içindeki ifade bir lambda ifadesidir.Birçok standart sorgu işleçleri, lambda ifadeleri parametre olarak alır, ancak bu uzantı yöntemleri için bir gereklilik değildir.Daha fazla bilgi için bkz. Lambda İfadeleri (C# Programlama Kılavuzu).

class ExtensionMethods2    
{

    static void Main()
    {            
        int[] ints = { 10, 45, 15, 39, 21, 26 };
        var result = ints.OrderBy(g => g);
        foreach (var i in result)
        {
            System.Console.Write(i + " ");
        }           
    }        
}
//Output: 10 15 21 26 39 45

Uzantı yöntemleri statik yöntemler olarak adlandırılır ancak örnek yöntemi söz dizimi kullanılarak çağrılır.İlk parametreleri hangi tür yöntemin çalıştığını belirtir, parametreden önce ise bu değiştirici bulunur.Uzantı yöntemleri yalnızca ad alanını kaynak kodunuza bir using yönergesi ile açıkça aldığınızda kapsam içindedir.

Aşağıdaki örnek String sınıfı için tanımlanmış bir uzantı yöntemini gösterir.Bunun iç içe ve genel olmayan bir statik sınıf içinde tanımlandığına dikkat edin:

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}

WordCount genişletme yöntemi bu using yönergeyle kapsama alınabilir:

using ExtensionMethods;

Ve bu sözdizimi kullanılarak bir uygulamadan çağrılabilir:

string s = "Hello Extension Methods";
int i = s.WordCount();

Kodunuzda örnek yöntemi sözdizimini ile genişletme yöntemi çağırırsınız.Ancak derleyici tarafından üretilen ara dil (IL), kodunuzu statik yöntemdeki bir çağrıya dönüştürür.Bu nedenle, kapsülleme ilkesi gerçekten ihlal edilmez.Aslında genişletme yöntemleri, genişletildikleri türde özel değişkenlere erişemez.

Daha fazla bilgi için bkz. Nasıl yapılır: Özel bir Genişletme Yöntemi Uygulama ve Arama (C# Programlama Kılavuzu).

Genel olarak, büyük olasılıkla kendinizinkileri uygulamayla kıyaslandığında genişletme yöntemlerini çok daha arayacaksınız.Genişletme yöntemleri örnek yöntem sözdizimi tarafından çağrıldığından istemci kodundan kullanmak için herhangi bir özel bilgi gerekli değildir.Belirli bir türe ilişkin olarak genişletme yöntemlerini etkinleştirmek için, yöntemlerin tanımlandığı ad alanı için bir using yönergesi eklemeniz yeterli olacaktır.Örneğin, standart sorgu işleçlerini kullanmak için bu using yönergesini kodunuza ekleyin:

using System.Linq;

(System.Core.dll öğesine başvuru eklemeniz gerekebilir.) Standart sorgu işleçlerinizin artık çoğu IEnumerable türünde kullanılabilen ek yöntemler olarak IntelliSense'de gösterildiğini fark edeceksiniz.

[!NOT]

Standart sorgu işleçleri String için IntelliSense'te görünmez olsa da hala kullanılabilir.

Derleme Zamanında Uzantı Yöntemleri Bağlama

Bir sınıfı veya arabirimi genişletmek için genişletme yöntemini kullanabilir, ancak bunları geçersiz kılamazsınız.Arabirim veya sınıf yöntemiyle aynı ada ve imzaya sahip genişletme yöntemi asla çağrılmaz.Derleme sırasında genişletme yöntemleri, her zaman türün kendisinde tanımlı örnek yöntemlerden daha düşük önceliğe sahiptir.Başka bir deyişle, bir türün Process(int i) adlı yöntemi varsa ve aynı imzaya sahip bir uzantı yönteminiz varsa, derleyici her zaman için örnek yöntemine bağlanır.Derleyici bir yöntem çağırmayla karşılaştığında, türün örnek yöntemleri önce bir eşleşme arar.Eşleşme bulunmazsa, tür için tanımlanan uzantı yöntemleri aranır ve ilk bulunan uzantı yöntemine bağlanılır.Aşağıdaki örnek, derleyicinin hangi genişletme yöntemine veya örnek yöntemine bağlanılacağını nasıl belirlediğini gösterir.

Örnek

Aşağıdaki örnek, C# derleyicisinin bir yöntem çağrısını türde bir örnek yöntemine mi yoksa bir genişletme yöntemine mi bağlayacağını belirlemede izlediği kuralları gösterir.Statik sınıf Extensions, IMyInterface uygulayan her tür için tanımlanmış genişletme yöntemleri içerir.A, B ve C sınıflarının tamamı arabirim uygular.

MethodB genişletme yöntemi asla çağrılmaz çünkü sınıflar tarafından zaten uygulanmış olan yöntemlerle adı ve imzası tam olarak eşleşmektedir.

Derleyici eşleştirilen imzayla bir oluşum yöntemi bulamadığında, varsa, eşleşen bir uzantı yöntemini bağlayın.

// Define an interface named IMyInterface. 
namespace DefineIMyInterface
{
    using System;

    public interface IMyInterface
    {
        // Any class that implements IMyInterface must define a method 
        // that matches the following signature. 
        void MethodB();
    }
}


// Define extension methods for IMyInterface. 
namespace Extensions
{
    using System;
    using DefineIMyInterface;

    // The following extension methods can be accessed by instances of any  
    // class that implements IMyInterface. 
    public static class Extension
    {
        public static void MethodA(this IMyInterface myInterface, int i)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, int i)");
        }

        public static void MethodA(this IMyInterface myInterface, string s)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, string s)");
        }

        // This method is never called in ExtensionMethodsDemo1, because each  
        // of the three classes A, B, and C implements a method named MethodB 
        // that has a matching signature. 
        public static void MethodB(this IMyInterface myInterface)
        {
            Console.WriteLine
                ("Extension.MethodB(this IMyInterface myInterface)");
        }
    }
}


// Define three classes that implement IMyInterface, and then use them to test 
// the extension methods. 
namespace ExtensionMethodsDemo1
{
    using System;
    using Extensions;
    using DefineIMyInterface;

    class A : IMyInterface
    {
        public void MethodB() { Console.WriteLine("A.MethodB()"); }
    }

    class B : IMyInterface
    {
        public void MethodB() { Console.WriteLine("B.MethodB()"); }
        public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
    }

    class C : IMyInterface
    {
        public void MethodB() { Console.WriteLine("C.MethodB()"); }
        public void MethodA(object obj)
        {
            Console.WriteLine("C.MethodA(object obj)");
        }
    }

    class ExtMethodDemo
    {
        static void Main(string[] args)
        {
            // Declare an instance of class A, class B, and class C.
            A a = new A();
            B b = new B();
            C c = new C();

            // For a, b, and c, call the following methods: 
            //      -- MethodA with an int argument 
            //      -- MethodA with a string argument 
            //      -- MethodB with no argument. 

            // A contains no MethodA, so each call to MethodA resolves to  
            // the extension method that has a matching signature.
            a.MethodA(1);           // Extension.MethodA(object, int)
            a.MethodA("hello");     // Extension.MethodA(object, string) 

            // A has a method that matches the signature of the following call 
            // to MethodB.
            a.MethodB();            // A.MethodB() 

            // B has methods that match the signatures of the following 
            // method calls.
            b.MethodA(1);           // B.MethodA(int)
            b.MethodB();            // B.MethodB() 

            // B has no matching method for the following call, but  
            // class Extension does.
            b.MethodA("hello");     // Extension.MethodA(object, string) 

            // C contains an instance method that matches each of the following 
            // method calls.
            c.MethodA(1);           // C.MethodA(object)
            c.MethodA("hello");     // C.MethodA(object)
            c.MethodB();            // C.MethodB()
        }
    }
}
/* Output:
    Extension.MethodA(this IMyInterface myInterface, int i)
    Extension.MethodA(this IMyInterface myInterface, string s)
    A.MethodB()
    B.MethodA(int i)
    B.MethodB()
    Extension.MethodA(this IMyInterface myInterface, string s)
    C.MethodA(object obj)
    C.MethodA(object obj)
    C.MethodB()
 */

Genel Yönergeler

Genel olarak, genişletme yöntemlerini tutumlu ve yalnızca gerektiğinde uygulamanızı öneririz.Mümkün olduğunda, varolan türü genişletmesi gereken istemci kodu, bunu varolan türden türetilmiş yeni bir tür oluşturarak yapmalıdır.Daha fazla bilgi için bkz. Devralma (C# Programlama Kılavuzu).

Kaynak kodunu değiştiremediğiniz bir türü genişletmek üzere genişletme yöntemini kullanırsanız, türün uygulanmasındaki bir değişikliğin genişletme yönteminizin kesilmesine neden olabileceği riskini göze alırsınız.

Verilen tür için uzantı yöntemleri uygularken aşağıdaki noktalara dikkate alın:

  • Türden tanımlı yöntemle aynı imzaya sahip değilse genişletme yöntemi asla çağrılmaz.

  • Uzantı yöntemleri ad alanı seviyesinde kapsama alınır.Örneğin Extensions adındaki tek bir ad alanında uzantı yöntemlerini içeren birden fazla statik sınıfınız varsa, bunların tümü using Extensions; yönergesiyle kapsama dahil edilecektir.

Uygulanan bir sınıf kitaplığı için derleme sürüm numarasının artıyor olmasını önlemek için uzantı yöntemleri kullanmamanız gerekir.Kaynak koduna sahip olduğunuz kitaplığa önemli işlevsellik eklemek isterseniz, derleme sürüm oluşturma için standart .NET Framework yönergelerini izlemeniz gerekir.Daha fazla bilgi için bkz. Derleme Sürümü Oluşturma.

Ayrıca bkz.

Başvuru

Lambda İfadeleri (C# Programlama Kılavuzu)

Kavramlar

C# Programlama Kılavuzu

Standart Sorgu İşleçlerine Genel Bakış

Diğer Kaynaklar

Paralel Programlama Örnekleri (bunlar birçok örnek genişletme yöntemleri içerir)

Örnek parametreler ve bunların etkilerine ilişkin dönüştürme kuralı

Uzantı yöntemlerinin diller arasında birlikte çalışabilirliği

Uzantı yöntemleri ve Curried Temsilciler

Genişletme yöntemi Bağlama ve Hata bildirimi