Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.85/20: Рейтинг темы: голосов - 20, средняя оценка - 4.85
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
1

Итерация по коллекции "внутри" объекта

11.07.2012, 17:26. Просмотров 4192. Ответов 9
Метки нет (Все метки)


Есть классы People и Person (полный код приводится просто так, в нём нет ничего особенного и думаю меня можно будет понять не просматривая полный код), в классе Person я сделал итераторы для foreach:
C#
1
2
3
4
5
public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
Но я также хочу чтобы у меня была возможность итерации ещё и по одному из полей этого типа Person, тоесть мне нужная такая себе обёртка сверху этого foreach так что я делаю так:
C#
1
2
3
4
5
        public IEnumerator Ages()
        {
            foreach (object person in Dictionary.Values)
                yield return (person as Person).Age; //свойство Age есть у каждой из Person и оно возвращает int
        }
Но компилятор меня не понимает и не позволяет теперь написать так:
C#
1
2
3
            People pp = new People();
            foreach (int age in pp.Ages)
                Console.Write(age + " ");
Ошибка:
Код
Ошибка	1	Оператор foreach не может использоваться для переменных типа "группа методов", так как "группа методов" не содержит открытого определения для "GetEnumerator"	c:\users\gepar\documents\visual studio 2012\Projects\People\People\Program.cs	188
Так как же мне сделать итерацию по такой себе "внутренней коллекции", по крайней мере создающей такое впечатление в коде из-вне класса.

Полный код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace People
{
    public class Person
    {
        private string name;
        private int age;
 
        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }
 
        public int Age
        {
            get
            {
                return age;
            }
            set
            {
                age = value;
            }
        }
 
        public Person(string name, int age)
        {
            this.name = name;
            this.age = age;
        }
 
        public override string ToString()
        {
            return name + ", " + age;
        }
 
 
        public static bool operator >(Person one, Person two)
        {
            return one.Age > two.Age;
        }
 
        public static bool operator <(Person one, Person two)
        {
            return !(one > two);
        }
 
        /*
        public static bool operator == (Person one, Person two)
        {
            if (ReferenceEquals(one, null) && ReferenceEquals(two, null))
                return true;
            else if (ReferenceEquals(one, null) || ReferenceEquals(two, null))
                return false;
 
            return one.age == two.age;
        }
       
 
        
        public static bool operator != (Person one, Person two)
        {
            return ! (one == two);
        }
        */
 
        public static bool operator >= (Person one, Person two)
        {
            return (one>two || one.age == two.age);
        }
 
        public static bool operator <=(Person one, Person two)
        {
            return (one < two || one.age == two.age);
        }
    }
 
 
 
    //хранит объекты Person, как ключ будет служить имя персоны
    public class People : DictionaryBase, ICloneable
    {
        public void Add(Person toAdd)
        {
            Dictionary.Add(toAdd.Name, toAdd);
        }
 
        public void Remove(Person toRemove)
        {
            Dictionary.Remove(toRemove.Name);
        }
 
        
        public Person this[string key]
        {
            get
            {
                return (Person)Dictionary[key];
            }
        }
 
 
        //для for each
        public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
 
        public IEnumerator Ages()
        {
            foreach (object person in Dictionary.Values)
                yield return (person as Person).Age;
        }
 
 
        //возвращает массив самых старших персон (количество элементов зависит от того
        //у скольки персон наибольший возраст совпадёт)
        public Person[] GetOldest()
        {
            int count = 0;
            Person oldest = null;
 
            foreach (object value in Dictionary.Values)
                //если oldest ещё ничего не назначалось то можно считать
                //что любая персона по сравнению с null объектом старше
                if (oldest == null)
                    oldest = value as Person;
                //иначе сохраняем указатель только если текущая персона старше
                else if (value as Person > oldest)
                    oldest = value as Person;
 
            if (oldest != null)
            {
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        count++;
 
                Person[] result = new Person[count];
                foreach (object value in Dictionary.Values)
                    if ((value as Person).Age == oldest.Age)
                        result[--count] = value as Person;
                return result;
            }
 
            return null;
        }
 
        public object Clone()
        {
            People newPeople = new People();
            foreach (Person pers in Dictionary.Values)
                newPeople.Dictionary.Add(pers.Name, pers);
 
            return newPeople;
        }
    }
 
 
 
    class Program
    {
        static void Main(string[] args)
        {
            People pp = new People();
            pp.Add(new Person("Adam", 22));
            pp.Add(new Person("Eva", 18));
            pp.Add(new Person("Andy", 22));
            pp.Add(new Person("Hero", 22));
 
            Person[] res = pp.GetOldest();
 
            if(res != null)
            foreach (Person pers in res)
                Console.WriteLine(pers);
            foreach (int age in pp.Ages)
                Console.Write(age + " ");
            Console.WriteLine();
        }
    }
}
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
11.07.2012, 17:26
Ответы с готовыми решениями:

можно ли удалить внутри строки лишние пробелы с методом str.Replace(" ", " ")
using System; using System.Linq; using System.Text; namespace ConsoleApplication { class...

Известны сорта роз, выращиваемых тремя цветоводами: "Анжелика", "Виктория", "Гагарин", "Ave Maria", "Катарина", "Юбилейн
Известны сорта роз, выращиваемых тремя цветоводами: &quot;Анжелика&quot;, &quot;Виктория&quot;, &quot;Гагарин&quot;, &quot;Ave...

Тип "Склад": "Ссылка на объект не указывает на экземпляр объекта"
#region using using System; using System.IO; #endregion namespace ConsoleApplicationTest...

Дан массив строк: "red", "green", "black", "white", "blue". Запишите в файл элементы массива построчно (в новой строке)
пишу так но не помогает: static void Main(string args) { string...

__________________
Помогаю в написании студенческих работ здесь.
Записывайтесь на профессиональные курсы С#-разработчиков‌
9
Эксперт .NET
14849 / 11236 / 2949
Регистрация: 17.09.2011
Сообщений: 18,819
11.07.2012, 17:29 2
После Ages скобок не хватает.
0
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 17:52  [ТС] 3
kolorotur, а вот и не угадал Я так уже пробовал.Так тоже нельзя, ошибка с прежним смыслом в общем-то:
Код
Ошибка	1	Оператор foreach не может использоваться для переменных типа "System.Collections.IEnumerator", так как "System.Collections.IEnumerator" не содержит открытого определения для "GetEnumerator"
Чего-то тут не хватает.

Добавлено через 2 минуты
Обычный GetEnumerator у меня конечно же реализован, но он у меня для того чтобы возвращать объекты типа Person. На всякий случай приведу код обоих моих реализаций итераторов:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
       //для итерации по объектам коллекции типа Person
       public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
        
        //для итерации по возрастам персон
        public IEnumerator Ages()
        {
            foreach (object person in Dictionary.Values)
                yield return (person as Person).Age;
        }
0
Эксперт .NET
14849 / 11236 / 2949
Регистрация: 17.09.2011
Сообщений: 18,819
11.07.2012, 17:55 4
Цитата Сообщение от Gepar Посмотреть сообщение
не угадал
Угадал - скобок там действительно не хватает.

C#
1
2
3
4
5
public IEnumerable<int> Ages()
        {
            foreach (object person in Dictionary.Values)
                yield return (person as Person).Age;
        }
0
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 18:13  [ТС] 5
kolorotur, ну ты дописал скобки не после Ages, а перед, да и скобки немного не те что в народе просто скобки. Но не суть, так тоже не собирается:
C#
1
Ошибка    1   Оператор foreach не может использоваться для переменных типа "System.Collections.Generic.IEnumerator<int>", так как "System.Collections.Generic.IEnumerator<int>" не содержит открытого определения для "GetEnumerator"
В общем-то оно хочет GetEnumerator
Но эта ошибка будет если в main написать
C#
1
foreach (int age in pp.Ages())
А я так понимаю эта коллекция должна всё же перебираться без скобок после Ages, те вот так:
C#
1
foreach (int age in pp.Ages)
Но в этом случае ошибка(а теперь уже ошибки) немного поменяются:
C#
1
2
Ошибка    1   Оператор foreach не может использоваться для переменных типа "группа методов", так как "группа методов" не содержит открытого определения для "GetEnumerator"
Ошибка    2   Использование оператора foreach с "группа методов" невозможно. Вызов "группа методов" использовался намеренно?
Добавлено через 2 минуты
Можно и не на моём примере объяснить как сделать чтобы в foreach не просто перебирать в виде
C#
1
foreach(Object obj in myCollection)
а чтобы перебирать в виде
C#
1
foreach(Object obj in myCollection.SecondCollection)
а я уже под свой пример потом код адаптирую.
0
Эксперт .NET
14849 / 11236 / 2949
Регистрация: 17.09.2011
Сообщений: 18,819
11.07.2012, 19:15 6
Цитата Сообщение от Gepar Посмотреть сообщение
ну ты дописал скобки не после Ages, а перед
Я не про угловые скобки говорю.
Ваш код из первого поста:

Цитата Сообщение от Gepar Посмотреть сообщение
C#
1
foreach (int age in pp.Ages)
А должно быть так:
C#
1
foreach (int age in pp.Ages())
Цитата Сообщение от Gepar Посмотреть сообщение
я так понимаю эта коллекция должна всё же перебираться без скобок после Ages, те вот так
Ages - это метод, потому скобки обязательны.

Цитата Сообщение от Gepar Посмотреть сообщение
Можно и не на моём примере объяснить как сделать чтобы в foreach не просто перебирать в виде
Я же вам в предыдущем сообщении привел пример.
1
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
11.07.2012, 23:23  [ТС] 7
Цитата Сообщение от kolorotur Посмотреть сообщение
А должно быть так:
да пробовал я и так и так перед тем как ответить в теме. Не собирается же всё равно, ну а чтобы было просто
C#
1
foreach (int age in pp.Ages)
(без Ages()) мне вероятно нужно было бы сделать get метод, но не в этом суть, суть сейчас в том что вариант с кодом
C#
1
2
3
4
5
6
7
8
9
10
11
12
        //для for each
        public new IEnumerator GetEnumerator()
        {
            foreach (object person in Dictionary.Values)
                yield return (Person)person;
        }
 
        public IEnumerator<int> Ages()
        {
            foreach (object person in Dictionary.Values)
                yield return (person as Person).Age;
        }
и кодом в main
C#
1
2
3
4
            People pp = new People();
            //...
            foreach (int age in pp.Ages())
                Console.Write(age + " ");
не собирается же. По прежнему жалуется:
Код
error CS1579: Оператор foreach не может использоваться для переменных типа "System.Collections.Generic.IEnumerator<int>", так как "System.Collections.Generic.IEnumerator<int>" не содержит открытого определения для "GetEnumerator"
0
Эксперт .NET
14849 / 11236 / 2949
Регистрация: 17.09.2011
Сообщений: 18,819
12.07.2012, 00:00 8
Gepar, сигнатура вашего метода:
C#
1
public IEnumerator<int> Ages()
Сигнатура метода из моего примера:
C#
1
public IEnumerable<int> Ages()
Как говорится, найдите 10 отличий.
1
1184 / 540 / 78
Регистрация: 01.07.2009
Сообщений: 3,517
12.07.2012, 11:59  [ТС] 9
kolorotur, я нашёл одно, с вас ещё девять
0
Эксперт .NET
14849 / 11236 / 2949
Регистрация: 17.09.2011
Сообщений: 18,819
12.07.2012, 12:17 10
Цитата Сообщение от Gepar Посмотреть сообщение
я нашёл одно, с вас ещё девять
Ну ладно, ладно - их там всего три
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.07.2012, 12:17

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь или здесь.

Получение свойства "lastlogon" объекта "user"
Доброго времени суток! Возник вопрос: Как правильно отобразить свойства &quot;lastlogon&quot; объекта...

Создание TcpChannel: не удалось привести тип объекта "System.Int32" к типу "System.String"
Всем привет! Скажите, пожалуйста, почему такая строчка не работает: TcpChannel channels = new...

Ошибка: Не удалось привести тип объекта "System.Int32" к типу "System.String"
if (Convert.ToInt32(textBox10.Text) &gt; Convert.ToInt32(sqlreader.GetString(0).ToString()) ) ...

Как исправить такую ошибку? Не удалось привести тип объекта "X" к типу "Y
Изучаю делегаты using System; class X { public int Val; } class Y : X { }


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.