Які типи класів можуть використовувати foreach
цикли?
Які типи класів можуть використовувати foreach
цикли?
Відповіді:
Насправді, строго кажучи, все, що вам потрібно використовувати foreach
, це загальнодоступний GetEnumerator()
метод, який повертає щось із bool MoveNext()
методом та ? Current {get;}
властивістю. Однак найпоширенішим значенням цього є "те, що реалізує IEnumerable
/ IEnumerable<T>
, повертаючи an IEnumerator
/ IEnumerator<T>
.
Побічно, це включає в себе все , що інвентар ICollection
/ ICollection<T>
, наприклад, що - небудь подібне Collection<T>
, List<T>
масиви ( T[]
) і т.д. Таким чином , будь-який стандартний «збір даних», як правило , підтримують foreach
.
Для підтвердження першого пункту наступні відмінно працюють:
using System;
class Foo {
public int Current { get; private set; }
private int step;
public bool MoveNext() {
if (step >= 5) return false;
Current = step++;
return true;
}
}
class Bar {
public Foo GetEnumerator() { return new Foo(); }
}
static class Program {
static void Main() {
Bar bar = new Bar();
foreach (int item in bar) {
Console.WriteLine(item);
}
}
}
Як це працює?
Цикл foreach подібний до foreach(int i in obj) {...}
свого роду прирівнюється до:
var tmp = obj.GetEnumerator();
int i; // up to C# 4.0
while(tmp.MoveNext()) {
int i; // C# 5.0
i = tmp.Current;
{...} // your code
}
Однак існують і варіації. Наприклад, якщо перечислювач (tmp) підтримує IDisposable
, він також використовується (аналогічно using
).
Зверніть увагу на різницю в розміщенні декларації " int i
" всередині (C # 5.0) порівняно з зовнішнім (вгору C # 4.0) циклом. Важливо, якщо ви використовуєте i
анонімний метод / лямбда всередині кодового блоку. Але це вже інша історія ;-с
for-loop
(це можна побачити при роботі з IL).
З MSDN :
Оператор
foreach
повторює групу вбудованих операторів для кожного елемента в масиві або колекції об'єктів .foreach
Оператор використовується для ітерації по колекції , щоб отримати потрібну інформацію, але не повинен бути використаний для зміни вмісту колекції , щоб уникнути непередбачуваних побічних ефектів. (наголос мій)
Отже, якщо у вас є масив, ви можете використовувати оператор foreach для ітерації масиву, наприклад:
int[] fibarray = new int[] { 0, 1, 2, 3, 5, 8, 13 };
foreach (int i in fibarray)
{
System.Console.WriteLine(i);
}
Ви також можете використовувати його для ітерації List<T>
колекції, наприклад:
List<string> list = new List<string>();
foreach (string item in list)
{
Console.WriteLine(item);
}
Відповідно до публікації в блозі Duck Notation , використовується набір качок.
Ось документи: Основна стаття З масивами з об’єктами колекції
Важливо зазначити, що "Тип елемента колекції повинен бути конвертованим до типу ідентифікатора". Це іноді неможливо перевірити під час компіляції і може генерувати виняток виконання, якщо тип екземпляра не може бути призначений для посилального типу.
Це призведе до винятку під час роботи, якщо у кошику з фруктами є не Apple, наприклад апельсин.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
Це безпечно фільтрує список лише до яблук за допомогою Enumerable.OfType
foreach(Apple a in fruitBasket.OfType<Apple>() )
IList<ListItem> illi = new List<ListItem>();
ListItem li = null;
foreach (HroCategory value in listddlsubcategory)
{
listddlsubcategoryext = server.getObjectListByColumn(typeof(HroCategory), "Parentid", value.Id);
li = new ListItem();
li.Text = value.Description;
li.Value = value.Id.ToString();
illi.Add(li);
IList<ListItem> newilli = new List<ListItem>();
newilli = SubCatagoryFunction(listddlsubcategoryext, "-->");
foreach (ListItem c in newilli)
{
illi.Add(c);
}
}
Корисну інформацію щодо цього питання також можна знайти на MSDN . Беручи суть з цієї статті:
Ключове слово foreach перераховує колекцію, виконуючи вбудований оператор один раз для кожного елемента в колекції:
foreach (var item in collection)
{
Console.WriteLine(item.ToString());
}
Компілятор переводить цикл foreach, показаний у наведеному вище прикладі, у щось подібне до цієї конструкції:
IEnumerator<int> enumerator = collection.GetEnumerator();
while (enumerator.MoveNext())
{
var item = enumerator.Current;
Console.WriteLine(item.ToString());
}
Ви можете спробувати це ...
List<int> numbers = new List<int>();
numbers.Add(5);
numbers.Add(15);
numbers.Add(25);
numbers.Add(35);
Console.WriteLine("You are added total number: {0}",numbers.Count);
foreach (int number in numbers)
{
Console.WriteLine("Your adding Number are: {0}", number);
}