foreach(var item in ...) и Энумераторы
От: teapot2  
Дата: 04.12.13 11:06
Оценка:
Господа знатоки .net и C#, подскажите, пожалуйста, как мне сделать правильно вот такую вещь:

Есть некий класс, содержащий внутри себя массив некотрых объектов. Хочу, чтобы оператор foreach с объектом этого класса был идентичен (со всеми синтаксическими деталями, т.е. с возможностью использования var в заголовке цикла) аналогичному оператору с содержащимся внутри него массивом.

Поясняю:

Скажем, есть класс, внутрь которого запрятан массив KeyValuePair<string, string>:
internal class MyDictionary
{
    private KeyValuePair<string, string>[] dict;
    public MyDictionary(KeyValuePair<string, string>[] dict)
    {
        this.dict = dict.ToArray();
    }
...
}

Я хочу, чтобы с объектом этого класса (точно так же, как и с содержащимся внутри него массивом) можно было сделать примерно так:
foreach (var item in myDictionary) 
{
    Console.WriteLine(item.Key + "=" + item.Value);
}


Насколько я понимаю, надо в моем классе определить энумератор. ОК. Определяю, получается вот что:
internal class MyDictionary
{
    private KeyValuePair<string, string>[] dict;
    public MyDictionary(KeyValuePair<string, string>[] dict)
    {
        this.dict = dict.ToArray();
    }
    public IEnumerator GetEnumerator()
    {
        return dict.GetEnumerator();
    }
}


Это работает не совсем так, как хотелось бы. То есть приведенный в предыдущем примере foreach не компилируется, пишет, что у объекта класса Object нет свойств Key и Value.
Приходится внутри заголовка foreach явно указывать тип элементов массива. Так работает, но это не совсем то, чего хотелось:
foreach (KeyValuePair<string, string> item in myDictionary) 
{
    Console.WriteLine(item.Key + "=" + item.Value);
}


Хорошо, пробуем перейти к обобщенным интерфейсам в определении класса:
internal class MyDictionary
{
....
    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
    {
        return (IEnumerator<KeyValuePair<string, string>>) dict.GetEnumerator();
    }
}


Так все компилируется, но при попытке foreach бросается исключение невалидного кастования, что вполне понятно:

System.InvalidCastException: Unable to cast object of type 'SZArrayEnumerator' to type 'System.Collections.Generic.IEnumerator`1[System.Collections.Generic.KeyValuePair`2[System.String,System.String]]'.


Повторяю вопрос: как мне доопределить мой класс myDictionary, содержащий внутри себя массив, чтобы вот этот код компилировался и работал корректно:
foreach (var item in myDictionary) 
{
    Console.WriteLine(item.Key + "=" + item.Value);
}
Re: foreach(var item in ...) и Энумераторы
От: QrystaL Украина  
Дата: 04.12.13 11:26
Оценка:
Здравствуйте, teapot2, Вы писали:
T>Повторяю вопрос: как мне доопределить мой класс myDictionary, содержащий внутри себя массив, чтобы вот этот код компилировался и работал корректно:
T>
T>foreach (var item in myDictionary) 
T>{
T>    Console.WriteLine(item.Key + "=" + item.Value);
T>}
T>


public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
    foreach (var item in dict)
    {
        yield return item;
    }
}
Re: foreach(var item in ...) и Энумераторы
От: hardcase Пират http://nemerle.org
Дата: 04.12.13 11:30
Оценка: 1 (1) +1
Здравствуйте, teapot2, Вы писали:

T>Хорошо, пробуем перейти к обобщенным интерфейсам в определении класса:

T>
T>internal class MyDictionary
T>{
T>....
T>    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
T>    {
T>        return (IEnumerator<KeyValuePair<string, string>>) dict.GetEnumerator();
T>    }
T>}
T>


Только нужно писать так:

internal class MyDictionary : IEnumerable<KeyValuePair<string, string>>
{
....
    public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
    {
        return ((IEnumerable<KeyValuePair<string, string>>) dict).GetEnumerator();
    }
}
/* иЗвиНите зА неРовнЫй поЧерК */
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.