2011-01-07 19 views
14

Aşağıdaki kodu dikkate alarak:IEnumerable olarak bir IQueryable kullanırsam Linq uzantı yöntemini çağırın, hangi uygulama çağrılır?

IQueryable<T> queryable; 

// something to instantiate queryable 

var enumerable = (IEnumerable<T>) queryable; 

var filtered = enumerable.Where(i => i > 3); 

Son satırda hangi uzatma yöntemi çağrılır?

Bu IEnumerable<T>.Where(...) mı? Veya IQueryable<T>.Where(...) çağrılacak çünkü gerçek uygulama hala acilen olabilir mi?

Muhtemelen ideal, normal polimorfizmin her zaman daha spesifik bir geçersiz kılma kullanacağı şekilde, çağrılacak IQueryable versiyonu için olacaktır.

Visual Studio'da Nerede yöntemini ve "Tanıma Git" i sağ tıklattığımda IEnumerable sürümüne gidiyorum, görsel bakış açısından anlam ifade eder.

Benim temel endişe eğer bir yerde Queryable almak için Linq NHRbernate kullanmak, ama ben daha genel IEnumerable imzası kullanan bir arayüz kullanarak bunu geçmek, ben ertelenmiş veritabanı yürütme harikaları kaybedersiniz !


Düzenleme: Iridium'un işaret ettiği gibi, Xzx74

public class Program 
    { 
     static void Main(string[] args) 
     { 
      var myString2 = new MyString2(); 
      var myString = (MyString)myString2; 
      Console.WriteLine(myString.Method()); 
      Console.ReadLine(); 
     } 
    } 

    public class MyString {} 

    public class MyString2 : MyString {} 

    public static class ExtensionMethods 
    { 
     public static string Method(this MyString instance) 
     { 
      return "MyString method"; 
     } 

     public static string Method(this MyString2 instance) 
     { 
      return "MyString2 method"; 
     } 
    } 

olarak adlandırılan Enumerable sürümü çıktı "MyString yöntemi" dir.

+0

Soruyu oylamayı unuttunuz ... Bulmak ilginçti :). –

+0

http://stackoverflow.com/questions/474074/overriding-extension-methods –

+3

Unutmayın, uzantı yöntemi sözdizimi, * statik yöntemle * ve statik yöntemlerin çağrılması için * sözdizimsel bir şekerdir. aramak*. * Çalışma zamanı * analizi istiyorsanız, bunu yapmak için kodu kendiniz yazmanız gerekir. Üstelik, IQ kod yoluna beklenmedik bir şekilde geri dönüşü olan bir IE için statik olarak bir IQ için arzu edilen * kabul edilmez *; Muhtemelen bir IE'ye atıyorsunuz çünkü * bir IQ olarak davranmak istemiyorsunuz! Eğer bir IQ olarak davranmak istiyorsanız, o zaman * atmayın *. Groucho kuralı: Bunu yaparken acıtıyorsa, bunu yapma *. –

cevap

8

Şu anda geçerli olan yanıt, uzantı yöntemleri değil, sanal yöntemlerle ilgilidir.

Bir IEnumerable'a bir IQueryable yazarsanız ve sonra uzantı yöntemlerinden birini (örneğin, sorunuzda Nerede (...)) çağırırsanız, Numaralandırılabilir sürümde, Queryable olanı değil, çağrılır.

3

Bu basit programı çalıştırdığınızda aşırı yüklenmenin nasıl çalıştığı açıklanır :). Cevap, temeldeki yöntemin çağrılacağıdır. Ve aynı şekilde IQueryable ve IEnumerable; Yani, orijinal nesnenin metodu, gerçek bir uygulamanın orijinal tipte olmasına rağmen, başka bir şey yapmasına rağmen. Ancak, bir uzantı yöntemi olduğunda, başvurulan nesnenin uzantı yöntemi kullanılır, bu nedenle uzantı yöntemindeki mantığa bağlıdır. Uzantı yöntemi, nesnenin gerçek bir tür olup olmadığını görmek ve daha sonra yöntemi yürütmeden önce geri yüklemek için akıllı bir kayıt gelebilir.

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyString2 myString2 = new MyString2(); 
     var myString = (MyString)myString2; 
     Console.WriteLine(myString); // prints "ToString of MyString2" 
     Console.WriteLine(myString.GiveMeTheString()); // prints "GiveMeTheString of MyString2" 
     Console.ReadLine(); 
    } 
} 

public class MyString 
{ 
    public string MyProperty { get; set; } 
    public override string ToString() 
    { 
     return "ToString of MyString"; 
    } 
} 
public class MyString2 : MyString 
{ 
    public string MyProperty { get; set; } 
    public override string ToString() 
    { 
     return "ToString of MyString2"; 
    } 
} 

public static class Extensions 
{ 
    public static string GiveMeTheString(this MyString myString) 
    { 
     return "GiveMeTheString of MyString"; 
    } 
    public static string GiveMeTheString(this MyString2 myString) 
    { 
     return "GiveMeTheString of MyString2"; 
    } 
} 
+0

Teşekkür ederim Tomas! Bunu kodlama yoluyla yapabilmem gerektiğini biliyordum ama beynim çalışmıyordu! En azından şimdi çözümü arayan başka birinin bu gönderiye katılacağını umuyorum. –

+0

Eklemeliyim - cevap daha spesifik (IQueryable) uzantı yönteminin çağrılacağıdır. –

+0

Bize en iyi şekilde olur. Oy vermeyi ve cevabı kabul etmeyi unutmayın, böylece diğer insanlar cevabı daha kolay bulabilir; Yani, eğer doğruysa. Ve bu kısmı cevabımdaki bir yere ekleyeceğim. –

İlgili konular