Официальный сайт студ.городка НГТУ
Программирование и БД » [c#] Смысл IEnumerable? 

#1  10.02.11 13:21

[c#] Смысл IEnumerable?

Код из мдсна:

Код: csharp:

using System;
using System.Collections;
 
public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }
 
    public string firstName;
    public string lastName;
}
 
public class People : IEnumerable
{
    private Person[] _people;
    public People(Person[] pArray)
    {
        _people = new Person[pArray.Length];
 
        for (int i = 0; i < pArray.Length; i++)
        {
            _people[i] = pArray[i];
        }
    }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            return new PeopleEnum(_people);
        }
}
 
public class PeopleEnum : IEnumerator
{
    public Person[] _people;
 
    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1;
 
    public PeopleEnum(Person[] list)
    {
        _people = list;
    }
 
    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }
 
    public void Reset()
    {
        position = -1;
    }
 
    public object Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}
 
class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };
 
        People peopleList = new People(peopleArray);
        foreach (Person p in peopleList)
            Console.WriteLine(p.firstName + " " + p.lastName);
 
    }
}
 
/* This code produces output similar to the following:
 *
 * John Smith
 * Jim Johnson
 * Sue Rabon
 *
 */


Можно свести к простому foreach без IEnumerable

Код: csharp:

using System;
using System.Collections;
 
public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }
 
    public string firstName;
    public string lastName;
}
 
//public class People : IEnumerable
//{
//    private Person[] _people;
//    public People(Person[] pArray)
//    {
//        _people = new Person[pArray.Length];
 
//        for (int i = 0; i < pArray.Length; i++)
//        {
//            _people[i] = pArray[i];
//        }
//    }
 
//    IEnumerator IEnumerable.GetEnumerator()
//    {
//        return new PeopleEnum(_people);
//    }
//}
 
//public class PeopleEnum : IEnumerator
//{
//    public Person[] _people;
 
//    // Enumerators are positioned before the first element
//    // until the first MoveNext() call.
//    int position = -1;
 
//    public PeopleEnum(Person[] list)
//    {
//        _people = list;
//    }
 
//    public bool MoveNext()
//    {
//        position++;
//        return (position < _people.Length);
//    }
 
//    public void Reset()
//    {
//        position = -1;
//    }
 
//    public object Current
//    {
//        get
//        {
//            try
//            {
//                return _people[position];
//            }
//            catch (IndexOutOfRangeException)
//            {
//                throw new InvalidOperationException();
//            }
//        }
//    }
//}
 
class App
{
    static void Main()
    {
        Person[] peopleArray = new Person[3]
        {
            new Person("John", "Smith"),
            new Person("Jim", "Johnson"),
            new Person("Sue", "Rabon"),
        };
 
        //People peopleList = new People(peopleArray);
        //foreach (Person p in peopleList)
        //    Console.WriteLine(p.firstName + " " + p.lastName);
 
        //простой foreach без IEnumerable
        foreach (Person p in peopleArray)
            Console.WriteLine(p.firstName + " " + p.lastName);
 
    }
}
 
/* This code produces output similar to the following:
 *
 * John Smith
 * Jim Johnson
 * Sue Rabon
 *
 */


Тогда в чем смысл (область применения) IEnumerable с его членами?

Вопрос 2. Чем отличается IEnumerable от IEnumerable<T> ?

Исправлено drug_detei (10.02.11 13:28)

Offline

#2  10.02.11 13:27

Re: [c#] Смысл IEnumerable?

а если тебе необходима своя экзотическая коллекция, например какое-нибудь хитрое дерево. Как ты тогда будешь использовать foreach ? придется реализовывать IEnumerable

Offline

#3  10.02.11 13:36

Re: [c#] Смысл IEnumerable?

То есть использование IEnumerable рекомендуется только для экзотических коллекций? :)

Offline

#4  10.02.11 15:10

Re: [c#] Смысл IEnumerable?

drug_detei, не знаю опечатка или нет, но правильно "МСДН".
По сабжу.
В своем втором примере ты использовал класс System.Array, который уже реализует IEnumerable. Этот класс имеет свой собственный синтаксис, поэтому его можно объявить таким образом

Код: C#:

  int [] a = new int [] {1,3,2}


Но он имеет много недостатков, поэтому далеко не всегда применим. Так что твое утверждение

drug_detei написал(а):

Можно свести к простому foreach без IEnumerable

в корне не верно, данный интерфейс используется в обоих приведенных тобой случаях.

Теперь о том когда, мне необходим был интерфейс:
1. При реализации экзотических коллекций :)
2. При использовании любых коллекций (в том числе словарей) с уже реализованным IEnumerable. Каждый раз, когда ты используешь foreach, ты используешь IEnumerable.
3. При использовании yield return;
4. При использовании linq to object. Там это фактически основной интерфейс.

IEnumerable<T> просто типизированный аналог  IEnumerable.

Offline

#5  10.02.11 17:23

Re: [c#] Смысл IEnumerable?

Udaw, спасибо, все понятно!

Offline

#6  10.02.11 21:07

Re: [c#] Смысл IEnumerable?

Еще разрешите спросить про уличную магию:

Код: csharp:

using System;
using System.Collections.Generic;
 
public static class EachExtension
{
    public static void Each<T>(this IEnumerable<T> enumberable, Action<T> action)
    {
        foreach (var item in enumberable)
        {
            action(item);
        }
    }
}
 
class App
{
    static void Main()
    {
        IEnumerable<string> x = new[] { "hello", "world", "how", "are", "you" };
 
        x.Each(p =>
        {
            Console.Write("Word:");
            Console.WriteLine(p);
        });
 
    }
}

Это готовая программа, компилится без ошибок.

Почему компилятор решает, что нужно брать метод Each<T> из верхнего класса, хотя явных ссылок между классами нет?

Откуда появляется p?

Исправлено drug_detei (10.02.11 21:12)

Offline

#7  12.02.11 00:22

Re: [c#] Смысл IEnumerable?

В данном случае метод Each - это так называемый метод расширения (Extencion Methods). Видишь ключевое слово this, перед первым параметром? Именно так компилятор узнает методы расширения. Для вызова метода расширения предусмотрен особый синтаксис. Если не ошибаюсь, то твой код:

Код: C#:

 x.Each(p =>
        {
            Console.Write("Word:");
            Console.WriteLine(p);
        });

эквивалентен следующему коду:

Код: C#:

 EachExtension.Each
        (
            x, 
            p => 
            { 
                Console.Write("Word:"); 
                Console.WriteLine(p); 
            }
        );

Если интересно, посмотри рефлектором, так ли это, я могу ошибаться. Таким образом, мы просто вызываем статический метод Each с двумя параметрами, где второй параметр - это делегат описываемые так:

Код: C#:

public delegate void Action<T>(T obj);

Т.е мы во второй параметр должны передать метод указанной сигнатуры. Что мы и делаем, только вместо имени готового метода используем анонимный метод. Анонимные методы используются начиная со второго фреймворка. С использованием анонимного метода мы могли бы записать:

Код: C#:

 EachExtension.Each
        (
            x,
            delegate(string p)
            {
                Console.Write("Word:");
                Console.WriteLine(p);
            }
        );

В довершении всего для сокращения записи анонимного делегата были использованы лямбда выражения, и код приобрел тот вид, которые ты привел. Таким образом, переменная p - это параметр анонимного метода, вызываемого из метода Each.

Итак, ключевые слова: анонимные методы, лямбда выражения, метод расширения (Extencion Methods).

Исправлено Udaw (12.02.11 00:32)

Offline

#8  12.02.11 18:42

Re: [c#] Смысл IEnumerable?

Спасибо, особенно за ключевые слова! Это просто какой-то космос!

Offline

#9  12.02.11 19:52

Re: [c#] Смысл IEnumerable?

Да, C# 3+ это реально космос;)
насчет IEnumerable и IEnumerable<T> - почитай generics(обобщения), если вкратце, то при итерировании по первому ты получишь object, по второму - типизированный объект T, плюс к этому, если у тебя коллекция Value типа, то будет сэкономлено время на boxing/unboxing из object

Offline

#10  13.02.11 12:06

Re: [c#] Смысл IEnumerable?

XuMiX написал(а):

плюс к этому, если у тебя коллекция Value типа, то будет сэкономлено время на boxing/unboxing из object

Можно примеры кода? А то не совсем понятен синтаксис инкапсуляции сигнатуры :)

Offline

Программирование и БД » [c#] Смысл IEnumerable? 

ФутЕр:)

© Hostel Web Group, 2002-2025.   Сообщить об ошибке

Сгенерировано за 0.123 сек.
Выполнено 14 запросов.