Учитывая следующий код:
IQueryable<T> queryable;
// something to instantiate queryable
var enumerable = (IEnumerable<T>) queryable;
var filtered = enumerable.Where(i => i > 3);
В последней строке, какой метод расширения вызывается?
Это IEnumerable<T>.Where(...)
? Или будет вызван IQueryable<T>.Where(...)
, потому что фактическая реализация по-прежнему явно запрашиваемая?
Предположительно, идеальным вариантом будет вызов версии IQueryable, точно так же, как нормальный полиморфизм всегда будет использовать более конкретное переопределение.
В Visual Studio, однако, когда я щелкаю правой кнопкой мыши по методу Where и «Перейти к определению», меня переводят в версию IEnumerable, что имеет смысл с визуальной точки зрения.
Моя главная проблема в том, что если где-нибудь в моем приложении я использую Linq для NHibernate, чтобы получить Queryable, но я передаю его с помощью интерфейса, использующего более общую сигнатуру IEnumerable, я потеряю чудеса отложенного выполнения базы данных!
Редактировать: Оказывается, что, как указал Иридиум, это Enumerable версия называется
.
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";
}
}
Вывод «Метод MyString».