Bir sınıfı c # uzantı yöntemleriyle nasıl genişletebilirim?


98

Uzatma yöntemleri sınıfa uygulanabilir mi?

Örneğin, DateTime öğesini aşağıdaki gibi çağrılabilen bir Tomorrow () yöntemini içerecek şekilde genişletin:

DateTime.Tomorrow();

Kullanabileceğimi biliyorum

static DateTime Tomorrow(this Datetime value) { //... }

Veya

public static MyClass {
  public static Tomorrow() { //... }
}

benzer bir sonuç için, ancak DateTime.Tomorrow'ı çağırabilmek için DateTime'ı nasıl uzatabilirim?

Yanıtlar:


69

Mevcut tür kısmi olarak işaretlenmedikçe var olan bir türe yöntem ekleyemezsiniz, yalnızca uzantı yöntemleri aracılığıyla var olan türün bir üyesi gibi görünen yöntemleri ekleyebilirsiniz . Bu durumda, uzantı yöntemleri bu türün örneklerini kullandığından, türün kendisine statik yöntemler ekleyemezsiniz.

Sizi bunun gibi kendi statik yardımcı yönteminizi oluşturmaktan alıkoyan hiçbir şey yoktur:

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

Bunun gibi kullanacağınız:

DateTime tomorrow = DateTimeHelper.Tomorrow;

7
ha woot? 6 ay içinde uygulanmadıysa ve Kumu'nun cevabı tam orada olmadıkça , bu aslında eksik görünüyor!
cregox

4
@Cawas bu eksik değil, Andrew bunun nasıl yapılacağını bir uzatma yöntemiyle değil, statik bir yardımcı ile gösteriyor (örnek olmadığı için).
Nick N.

1
Haklısın Nick. Yine de uzatma yöntemlerini tercih ederim! ;)
cregox

2
Extensionmethod.net/csharp/datetime hakkında ne var ? IMHO, öğrenme eğrisi en aza indirmek için daha iyi örnekler tam kaynak kodu ve iyi desenleri ile gerçek uygulamalardır
Kiquenet

3
Bu kodla ilgili sorun, herhangi bir DateTime nesnesinde değil, yalnızca DateTime.Now üzerinde çalışmasıdır. Bir yardımcı program olarak, önceki (veya gelecekteki) bir günden sonraki günü belirlemek için kullanmak isteyebilir. DateTime.Now her aradığınızda belirlenir ...
MintGrowth

182

Bir uzatma yöntemi kullanın .

Ör:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

Kullanım:

DateTime.Now.Tomorrow();

veya

AnyObjectOfTypeDateTime.Tomorrow();

2
Shuggy'nin cevabı da benzer bir çözüme ışık tuttu.
cregox

8
'ExtensionMethods'u kullanmayı' unutmayın; bunun için belgenizin üst kısmında.
Luke Alderton

Neden DateTime.Tomorrow () yapamıyorum?
lawphotog

Merhaba lawphotog, bu uzantının bir nesneye ihtiyacı var, burada DateTime bir nesne değil bir yapıdır.
Kumu

4
Önceki yorumlarda belirtildiği gibi (görünüşe göre benim için yeterince açık değildi), DateTime.Tomorrow()bir sınıfın ve bir sınıf yapısının yalnızca ANLAŞMALARI üzerinde çalışan genişletme yöntemlerini KULLANAMAYACAKSINIZ. Bir sınıf yapısında statik bir yöntemi "genişletmek" için Andrew'un cevabını veya Shuggy'nin cevabını takip edin .
Alex

18

Uzantı yöntemleri, ilk parametresi T türünün bir örneği olan statik yöntemlerin T'de bir örnek yöntemmiş gibi görünmesini sağlayan sözdizimsel şekerdir.

Bu nedenle, kod okuyucuyu bir uzantı yönteminden daha fazla karıştırmaya hizmet edeceğinden (tam olarak nitelendirilmiş gibi göründükleri ancak gerçekte o sınıfta tanımlanmadıkları için), 'statik genişletme yöntemleri' yaptığınız yerde fayda büyük ölçüde kaybolur. hiçbir sözdizimsel kazanç için (örneğin Linq içinde akıcı bir tarzda aramaları zincirleyebilmek).

Uzantıları yine de bir kullanarak kapsama getirmeniz gerekeceğinden, oluşturmanın daha basit ve daha güvenli olduğunu iddia ediyorum:

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

Ve sonra bunu şu yolla kodunuzda kullanın:

WriteLine("{0}", DateTimeUtils.Tomorrow)

11

Cevaba en yakın olanı, bir System.Typenesneye bir genişletme yöntemi eklemektir . Hoş değil ama yine de ilginç.

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

Aksi takdirde, IMO Andrew ve ShuggyCoUk daha iyi bir uygulamaya sahiptir.


Bu yaklaşımla ilgili sorunlar var. "Typeof (...)" yazmak zorunda kalmak uygun değildir ve intellisense ile her türden uzantı görürsünüz. Yine de, düşünmediğim ilginç bir yaklaşım, +1.
Meta-Knight

@ Meta-Knight Doğru, bu yüzden şahsen ben diğerinin cevabını tercih ediyorum. Cevabım OP sorusuna en yakın sözdizimine sahip olacaktır, ancak bu sorunu çözmenin en iyi yolu bu değildir.
Adrian Godong

Typegerekli herhangi bir başka tür ile değiştirilebilir. Onunla kullanıyorum Fromve mükemmel çalışıyor. sanırım bu yanıt genel ama doğru
Katia

3

Kumu ile aynı şeyi yapardım

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

ancak bu yeni DateTime () gibi adlandırın. Yarın ();

DateTime.Now.Tomorrow () 'dan daha çok şey gördüğünü düşünün;


1
Ve bunu Kumu'nun cevabına yorum olarak yazma şansını kaçırdın! : P
cregox

3

Türe değişiklik gerektirmeden yeni yöntemler ekleyerek mevcut türleri genişletme yeteneği sağlarlar. Örnek yöntemi sözdizimini kullanarak bir uygulama içinde genişletilmiş türdeki nesnelerden yöntemlerin çağrılması, "genişletme" yöntemleri olarak bilinir. Uzantı yöntemleri, türdeki örnek üyeleri değildir. Hatırlanması gereken en önemli nokta, statik yöntemler olarak tanımlanan uzantı yöntemlerinin, yalnızca ad alanı using yönergesi aracılığıyla uygulama kaynak kodunuza açıkça içe aktarıldığında kapsam dahilindedir. Uzantı yöntemleri statik yöntemler olarak tanımlansa da, yine de örnek sözdizimi kullanılarak çağrılırlar.

Tam örneği buradan kontrol edin http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

Misal:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }

3

Ben de benzer bir şey arıyordum - Uzantı Yöntemleri sağlayan sınıflar üzerindeki kısıtlamaların bir listesi. Kısa bir liste bulmak zor görünüyor, bu yüzden burada:

  1. Özel veya korumalı bir şeye sahip olamazsınız - alanlar, yöntemler vb.

  2. İçindeki gibi statik bir sınıf olmalıdır public static class....

  3. Sınıfta yalnızca yöntemler olabilir ve hepsinin genel statik olması gerekir.

  4. Geleneksel statik yöntemlere sahip olamazsınız - bu argümanı içermeyenlere izin verilmez.

  5. Tüm yöntemler başlamalıdır:

    public static ReturnType MethodName (bu SınıfAdı _this, ...)

Yani ilk argüman her zaman bu referanstır.

Bunun yarattığı örtük bir sorun vardır - herhangi bir çeşit kilit gerektiren yöntemler eklerseniz, bunu sınıf düzeyinde gerçekten sağlayamazsınız. Tipik olarak özel bir örnek seviyesi kilidi sağlarsınız, ancak herhangi bir özel alan eklemek mümkün değildir, bu da size bunu bazı dış sınıflarda genel statik olarak sağlama vb. Gibi bazı çok garip seçenekler bırakır. C # dilinin bunlar için tasarımda kötü bir dönüş yaptığına işaret eder .

Çözüm, Extension Method sınıfınızı normal bir sınıfa yönelik bir Facade olarak kullanmaktır ve Extension sınıfınızdaki tüm statik yöntemler, muhtemelen bir Singleton kullanarak gerçek sınıfı çağırır .


2

Ne yazık ki bunu yapamazsınız. Yine de faydalı olacağına inanıyorum. Yazması daha doğaldır:

DateTime.Tomorrow

şundan:

DateTimeUtil.Tomorrow

Bir Util sınıfıyla, bir yerine iki farklı sınıfta statik bir yöntemin varlığını kontrol etmeniz gerekir.


1

Cevabımızı detaylı bir açıklama ile geliştirdik, artık uzatma yöntemini anlamak daha kolay

Uzatma yöntemi : Mevcut sınıfın davranışını alt sınıflandırma kullanmadan veya orijinal sınıfı veya yapıyı değiştirmeden veya yeniden derlemeden genişletebileceğimiz bir mekanizmadır.

Özel sınıflarımızı, .net çerçeve sınıflarımızı vb. Genişletebiliriz.

Uzantı yöntemi aslında statik sınıfta tanımlanan özel bir statik yöntem türüdür.

Gibi DateTime zaten yukarıda alındığı için bu dersi açıklama için almadık.

Aşağıda örnek

// Bu, yalnızca bir yöntemi olan mevcut bir Hesap Makinesi sınıfıdır (Ekle)

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.