Вопрос

Я использую следующий код, чтобы позволить MyClass использовать Foreach. Но я довольно новичок в программировании и испытываю некоторые трудности в понимании следующего кода. Я описал свои проблемы в комментариях. Я был бы благодарен за предоставление некоторой информации.

    public class MyClass : IEnumerable<string> 
    {  
    //1) What is IEnumerator for?
        // Whats the difference between IEnumerator and IEnumerable
    public IEnumerator<string> GetEnumerator()     
    {
             yield return "first";         
             yield return "second";     
    }      
    //2) What is it for?  It just calls above method 
   IEnumerator IEnumerable.GetEnumerator()
         {
             return GetEnumerator(); 
         } 
    }
   //3) Lastly what benefits I have from implementing genetic interface 
   //IEnumerable<string> instead of just IEnumerable
Это было полезно?

Решение

В чем разница между Ienumerator и Ienumerable?

Ответ Джейсона хорош, но я подумал, что просто добавлю, как я думаю об этом. Представьте, что у вас есть последовательность:

1, 1, 2, 3, 5, 8, 13, ...

Теперь представьте, что у вас есть стрелка, указывающая на какую -то положение этой последовательности:

1, 1, 2, 3, 5, 8, 13, ...
         ^

«Стрелка» - это объект, который может сделать две вещи. Во -первых, это может дать вам то, на что это указывает. Во -вторых, это может указывать на следующее.

Ienumerator - это стрела. У него есть свойство, текущее, которое дает вам то, на что он указывает. У него есть метод, movenext (), который указывает на следующее.

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

Ienumerable - это фабрика стрелы. У него есть метод, GetEnumerator, который дает вам стрелку для первого элемента последовательности.

Хорошее свойство этой схемы заключается в том, что вы можете иметь несколько стрел, указывающих на разные места в одной и той же последовательности.

Каковы преимущества внедрения общего интерфейса, связанного с тем, чтобы просто оборудовать?

Предположим, что последовательность имеет целые числа. Если вы реализуете IEnumerable Затем, когда вы говорите

foreach(int x in mysequence)

На самом деле это будет преобразовать INT в последовательности в объект, бокс, а затем немедленно отстранить объект обратно в целое число, добавив совершенно ненужное распределение памяти в каждую операцию. Если компилятор знает, что последовательность имеет целые числа, он может пропустить ненужную операцию бокса.

Предположим, что последовательность из строк. Если вы реализуете IEnumerable<string> Тогда вы можете сказать:

string first = mysequence.First();

Если вы этого не сделаете, то вы должны сказать

string first = (string)mysequence.First();

который не нужен и подвержен ошибке. Вместо того, чтобы инструктировать компилятор через актерский состав, который тип является строкой, вы можете просто гарантия что тип является строкой с помощью системы типа.

Другие советы

1) Что IEnumerator за? В чем разница между IEnumerator а также IEnumerable?

IEnumerator это интерфейс, который представляет методы, которые позволяют вам перечислять последовательность. Разница между IEnumerator а также IEnumerable заключается в том, что первый представляет контракт для объектов, которые позволяют вам перечислять последовательность, а последний представляет контракт для объектов, которые являются последовательности, которые можно перечислять.

public IEnumerator<string> GetEnumerator() {
         yield return "first";         
         yield return "second";     
}      


IEnumerator IEnumerable.GetEnumerator() {
    return GetEnumerator(); 
} 

2) Для чего это? Это просто вызывает выше метод.

Первый представляет собой реализацию метода GetEnumerator по контракту IEnumerable<string>. Анкет Последний представляет явную реализацию метода GetEnumerator по контракту IEnumerable. Анкет Проблема в том, что у обоих контрактов есть названный метод GetEnumerator Но с разными типами возврата, чтобы метод не мог одновременно удовлетворять оба контракта (любой класс реализация IEnumerable<T> также должен реализовать IEnumerable в качестве IEnumerable<T> : IEnumerable) Последний вызывает реализацию IEnumerable<string>.GetEnumerator как это разумная реализация, которая возвращает IEnumerator в качестве IEnumerator<string> : IEnumerator.

3) Наконец, какие преимущества у меня есть от реализации общего интерфейса IEnumerable<string> вместо просто IEnumerable?

Сильная набор. Вы знаете, что элементы в последовательности IEnumerable<string> все примеры String в то время как вы этого не знаете IEnumerable и может в конечном итоге попытаться подать элемент последнего в экземпляр String когда это не может быть.

Это заявление о IEnumerable<T>:

public interface IEnumerable<out T> : IEnumerable
{
    IEnumerator<T> GetEnumerator();
}

У тебя нет выбора, ты имеют Для реализации негенерического Ienumerable Interface также. Вы получите ошибку компиляции, если вы опустите реализацию ienumerable.getEnumerator (). Это багаж, оставшийся от дни .NET 1.X, когда дженерики еще не были доступны, и переходный период для .NET 2.0, где ему необходимо поддерживать взаимосвязь с сборками .NET 1.X. Мы застряли с этим.

1) Для чего подлежит ienumerator?

Ienumerator является реальной рабочей частью с Movenext () и нынешними участниками.

В чем разница между ienumerator и ienumerable

Ienumerable - это интерфейс для коллекции, чтобы сигнализировать о том, что у него есть getenumerator ().

2) [Не генеральный getenumerator] для чего он? Это просто вызовы выше метод

Негенерический метод только для обратной совместимости. Обратите внимание, что он максимально перемещается из поля зрения как можно больше, используя явную реализацию. Реализуйте его, потому что вы должны, а затем забудьте об этом.

3) Наконец, какие преимущества у меня есть от реализации генетического интерфейса, а не просто оборудованного

При использовании с foreach Адавация невелика, так как Foreach будет печатать переменную цикла. Это позволит вам использовать var в Foreach:

foreach (var s in myClassInstance)     // needs `IEnumerable<string>` 
foreach (string s in myClassInstance)  // works with  `IEnumerable` as well 

Но с IEnumerable<string> У вас также есть интерфейс, безопасный для типов, с другими областями, особенно LINQ:

MyClass mc = new MyClass ();
string s = mc.FirstOrDefault();

GetEnumerator существует с тех пор, как до того, как общие были введены в язык, чтобы не нарушать ранее существовавший код, метод по умолчанию вызывает общую реализацию.

С общим перечислением потребителю вашего класса не нужно отбрасывать каждый элемент на строку при итерации.

Что касается 3 -го вопроса (зачем использовать дженерики?) Вот несколько ответов:

Должны ли мы использовать общую коллекцию для повышения безопасности и производительности?

Короче говоря, используйте общие коллекции каждый раз, когда можете.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top