Share via


Uzantı yöntemleri (C# Programlama Kılavuzu)

Uzantı yöntemleri "yöntemleri için varolan türlerini yeni türetilmiş tür oluşturma, yeniden veya aksi takdirde özgün türü değiştirme eklemek" sağlar. Uzantı yöntemleri statik yöntemi özel bir tür olan, ancak genişletilmiş türün örnek yöntemleri sanki adlandırılırlar. C# ve Visual Basic içinde yazılmış istemci kodu için genişletme yöntemi ve gerçekte bir türünde tanımlanan yöntemleri çağırmak arasında belirgin fark yoktur.

En yaygın genişletme yöntemleridir LINQ varolan sorgu işlevsellik ekleyen standart sorgu işleçler System.Collections.IEnumerable ve System.Collections.Generic.IEnumerable<T> türleri. Standart sorgu işleçleri kullanmak için önce bunları kapsamlı içine getirmek bir using System.Linq yönergesi. Sonra uygulayan herhangi bir tür IEnumerable<T> örnek yöntemleri gibi görünüyor GroupBy, OrderBy, Averageve benzeri. "Nokta" yazdığınızda IntelliSense deyimi tamamlama ek bu yöntemleri bir örneğinden sonra görebilirsiniz bir IEnumerable<T> gibi yazın List<T> veya Array.

Aşağıdaki örnek, standart sorgu işlecini çağırmak nasıl gösterir OrderBy dizisi yöntemi. Lambda ifade parantez içinde ifadesidir. Birçok standart sorgu işleçler lambda ifadeleri parametreler olarak alır, ancak bu uzantı yöntemleri için bir gereksinim değildir. Daha fazla bilgi için bkz. Lambda ifadeleri (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öntemleri olarak tanımlanmıştır, ancak örnek yöntemi sözdizimini kullanarak olarak adlandırılır. Yöntemin tür üzerinde çalışır ve parametre koyarak kendi ilk parametresi belirtir Bu değiştirici. Genişletme yöntemleri, açıkça ad alanı ile kaynak kodu içine alırken kapsamı içinde olan bir using yönergesi.

Aşağıdaki örnek için tanımlanan bir uzantı yöntemini gösterir System.String sınıf. Not içinde yuvalanmış olmayan, genel olmayan statik sınıf tanımlanır:

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 duruma bu kapsam içine using yönergesi:

using ExtensionMethods;

Ve bu sözdizimini kullanarak bir uygulamasından ç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ır. Ancak, derleyici tarafından oluşturulan ara dili (IL) kodunuzu statik yöntemi bir çağrıya dönüştürecektir. Bu nedenle, saklama İlkesi gerçekten ihlal değil. Aslında, genişletme yöntemleri, genişletme türü özel değişkenleri erişemiyor.

Daha fazla bilgi için bkz. Nasıl yapılır: uygulamak ve özel bir uzantısı yöntemi (C# Programlama Kılavuzu).

Genel olarak, büyük olasılıkla genişletme yöntemleri uygulayan kıyasla çok daha sık kendi sizi arayacaktır. Örnek yöntemi sözdizimini kullanarak genişletme yöntemleri denir çünkü istemci kodundan kullanılacak özel hiçbir bilgisi gereklidir. Belirli bir türü için uzantı yöntemlerini etkinleştirmek için yalnızca Ekle bir using yönergesi yöntemleri tanımlanan ad alanı. Örneğin, standart sorgu işleçleri kullanmak için bu ekleyin using kodunuzu yönergesi:

using System.Linq;

(Siz de System.Core.dll başvuru eklemeniz gerekebilir.) Standart sorgu işleçler şimdi IntelliSense'de çoğu için ek yöntemler olarak göründüğünü fark edersiniz IEnumerable<T> türleri.

Not

Standart sorgu işleçler için IntelliSense görünmez olsa da String, bunlar hala kullanılabilir.

Uzantı yöntemleri derleme zamanında denetim ekleme

Bir sınıfın veya arayüzün genişletmek için ancak bunları geçersiz uzantı yöntemlerini kullanabilirsiniz. Bir uzantı ile aynı ada ve imzaya arayüz olarak veya sınıf yöntemini hiçbir zaman çağrılmaz. Derleme zamanında genişletme yöntemleri her zaman türü içinde tanımlanan örnek yöntemleri daha düşük önceliğe sahiptir. Diğer bir deyişle, bir türü olan bir yöntem adlı Process(int i)ve bir uzantı yöntemiyle aynı imzaya sahip, derleyici her zaman örnek yöntemi bağlayacaksınız. Derleyici bir yöntem çağırma karşılaştığında ilk türün örnek yöntemleri, bir eşleşme arar. Eşleşme bulunursa, herhangi bir genişletme yöntemleri türü için tanımlanmış olan ve bulduğu ilk uzatma yönteminin bağlamak için arama yapar. Aşağıdaki örnek derleyici hangi uzantısı veya bağlamak için örnek yöntemini nasıl belirlediğini gösterir.

Örnek

Aşağıdaki örnek C# derleyicisi belirleme türü üzerinde örnek yöntemi veya genişletme yöntemi için bir yöntem çağrısı bağlamak mı takip kuralları gösterir. Statik sınıf Extensions uygulayan herhangi bir türü için tanımlanmış uzantı yöntemleri içeren IMyInterface. Sınıfları A, B, ve C arabirimini uygulayan tüm.

MethodB Genişletme yöntemi adını ve imza zaten sınıfları tarafından uygulanan yöntemlerin tam olarak eşleşmesi nedeniyle hiçbir zaman çağrılır.

Derleyici eşleşen bir imzaya sahip bir örnek yöntemi bulamadığında, varsa, eşleşen bir uzantısı yöntem bağlayacaksınız.

// 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öntemleri uygulamak öneririz tutumlu ve yalnızca varsa için. Mümkün olduğunda, varolan bir türünü genişletmeniz gerekir istemci kodu yeni bir türü var olan türden türetilmiş oluşturarak yapmalısınız. Daha fazla bilgi için bkz. Kalıtım (C# Programlama Kılavuzu).

Kaynak kodunu değiştiremezsiniz türü genişletmek için bir uzantı yöntemini kullanırken, ayırmak, genişletme yöntemi türü'nde bir değişiklik neden olacak riskiyle karşılaşırsınız.

Verilen tür için uzantı yöntemleri uygularsanız, followingpoints hatırlayın:

  • Bir uzantı yöntemini türünde tanımlanan bir yöntem olarak aynı imzaya sahip olması durumunda hiçbir zaman çağrılmaz.

  • Genişletme yöntemleri ad alanı düzeyinde kapsam içine yapılmasıdır. Adlı tek bir ad uzayında uzantı yöntemleri içeren birden çok statik sınıflar varsa, örneğin, Extensions, bunların tümü tarafından kapsam içine duruma getirilir using Extensions; yönergesi.

Size uygulanan bir sınıf kitaplığı için uzantı yöntemleri derleme sürüm numarası artırılmıyor önlemek için kullanmamanız gerekir. Kaynak koduna sahip bir kitaplığa önemli işlevler eklemek isterseniz, derleme sürüm oluşturma için standart .NET Framework yönergeleri uygulamalısınız. Daha fazla bilgi için bkz. Derleme sürüm oluşturma.

Ayrıca bkz.

Başvuru

Lambda ifadeleri (C# Programlama Kılavuzu)

Kavramlar

C# Programlama Kılavuzu

Standart sorgu işleçler genel bakış

Diğer Kaynaklar

Dönüştürme kuralları örneği için parametreler ve etkilerini

diller arasında birlikte çalışabilirlik genişletme yöntemleri

genişletme yöntemleri ve temsilciler Curried

genişletme yöntemi bağlama ve hata bildirimi