Какие типы классов могут использовать циклы foreach?
Как работают циклы foreach в С#?
Ответ 1
На самом деле, строго, все, что вам нужно использовать foreach, является общедоступным методом GetEnumerator(), который возвращает что-то с помощью метода bool MoveNext() и свойства ? Current {get;}. Однако самым общим значением является то, что реализует IEnumerable/IEnumerable<T>, возвращая 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) {...} kinda, равен:
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" внутри (С# 5.0) по сравнению с внешним (до С# 4.0) в цикле. Это важно, если вы используете i в анонимном методе/лямбда внутри вашего кодового блока. Но это еще одна история; -p
Ответ 2
От 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);
}
Ответ 3
Согласно сообщению блога Duck Notation, используется утиная печать.
Ответ 4
Здесь docs: Основная статья С массивами С объектами коллекции
Важно отметить, что "Тип элемента коллекции должен быть конвертирован в тип идентификатора". Это иногда невозможно проверить во время компиляции и может генерировать исключение во время выполнения, если тип экземпляра не присваивается ссылочному типу.
Это создаст исключение во время выполнения, если в корзине фруктов есть не яблоко, например оранжевое.
List<Fruit> fruitBasket = new List<Fruit>() { new Apple(), new Orange() };
foreach(Apple a in fruitBasket)
Это безопасно фильтрует список только в Яблоках, используя Enumerable.OfType
foreach(Apple a in fruitBasket.OfType<Apple>() )
Ответ 5
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);
}
}