LINQ возвращает интерфейс? - PullRequest
5 голосов
/ 25 августа 2011

Просто просматривая учебные пособия LINQ на MSDN и сталкивайтесь со следующим кодом:

IEnumerable<int> numQuery1 = 
            from num in numbers
            where num % 2 == 0
            orderby num
            select num;

Я не понимаю, как возвращается интерфейс?Насколько я понимаю, интерфейс - это просто схема для класса, и, конечно, он не может содержать никаких данных.

Мне бы очень хотелось, чтобы это прояснили.

Ответы [ 7 ]

10 голосов
/ 25 августа 2011

Интерфейс представляет собой контракт на возвращаемое значение: Linq на самом деле не скажет что он вернет (как в реальном классе), но он гарантирует, что он ведет себя как IEnumerable<int>, то есть возвращаемый класс реализует этот интерфейс. Это может быть List<int> или WhackyLinqInternalEnumerable<int> - но вам все равно, потому что все, что вас интересует, это интерфейс (что вы можете сделать с объектом).

Одна вещь, которая может сбить вас с толку, - это разница между переменной и объектом, который она представляет: для (ссылочных) типов переменная просто «указывает» на объект. Вы можете иметь много переменных, «указывающих» на один и тот же объект. Им не обязательно иметь один и тот же тип, но объект, на который они все указывают, должен быть того же типа, что и переменная, подтип или (в случае переменной с типом интерфейса) должен реализовывать одну и ту же переменную.

6 голосов
/ 25 августа 2011

Вы получаете реализацию интерфейса, но работаете с ним через интерфейс - вы не знаете конкретный тип.

http://en.wikipedia.org/wiki/Interface_(computing)

0 голосов
/ 25 августа 2011

Думайте об этом так: сейчас 5 часов, и вы хотите пойти домой. На данный момент не имеет значения, как вы туда доберетесь: (абстрактно) вы можете создать экземпляр класса Car или класса Bike или даже класса Tank . Но если честно, тебя это волнует? Вы просто берете экземпляр любого инструмента IVehicle и просто идете домой.

0 голосов
/ 25 августа 2011

Если метод возвращает интерфейс, конечно, он должен вернуть фактический объект класса, который реализует конкретный интерфейс.

Это обычно рассматривается как "контракт", который метод имеет с вызывающей стороной.,Метод говорит: «Я всегда буду возвращать то, что имеет именно это поведение».

В этом конкретном случае код запроса LINQ должен возвращать любой объект, который реализует интерфейс IEnumerable<int>.

Другими словами, если вы сделаете это:

Debug.WriteLine(numQuery1.GetType().FullName);

, вы увидите возвращаемый тип фактический .

Следующий пример:

var numbers = new[] { 1, 2, 3, 4 };
IEnumerable<int> numQuery1 = 
        from num in numbers
        where num % 2 == 0
        orderby num
        select num;

Debug.WriteLine(numQuery1.GetType().FullName);

выведет это в .NET 4.0:

System.Linq.OrderedEnumerable`2 [[System.Int32, mscorlib, Версия = 4.0.0.0, Культура = нейтральная, PublicKeyToken = b77a5c561934e089], [System.Int32, mscorlib, версия = 4.0.0.0, культура = нейтральная, PublicKeyToken = b77a5c561934e089]]

, которая указывает, что это System.Linq.OrderedEnumerable<int, int>.

однако , и это реальная точка зрения, вам все равно.Все, что вам нужно знать, это то, что запрос LINQ возвращает что-то , которое реализует этот интерфейс.В будущей версии .NET код может на самом деле возвращать что-то еще, но все же объект, который реализует IEnumerable<T>.

0 голосов
/ 25 августа 2011

Это означает, что запрос linq возвращает экземпляр класса, который удовлетворяет этому интерфейсу.Вы, вызывающая сторона, не должны знать, что такое класс, а только то, что он удовлетворяет указанному интерфейсу.

0 голосов
/ 25 августа 2011
public interface IMyInterface {
}

public class MyCoolInterfaceImplementation : IMyInterface  {
}

//somewhere in code 

IMyInterface inter = new MyCoolInterfaceImplementation (); 

Это совершенно правильный код.Та же идея содержится в предоставленном вами коде.

0 голосов
/ 25 августа 2011

Но вы можете создать объект типа interface ... возможно, не путайте между типом класса и типом интерфейса

Ниже приведен пример: как вы можете создать тип интерфейса: то же самое происходит в вышеупомянутом случае

interface IA 
{
   void methodA();
}

Class B : IA
{

}

Class C
{
   IA a = new B();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...