Вот еще одно решение этой проблемы, с акцентом на поддержание синтаксиса как можно ближе к стандартному foreach
.
Этот вид конструкции полезен, если вы хотите, чтобы ваши взгляды выглядели красиво и чисто в MVC. Например, вместо того, чтобы писать это обычным способом (который трудно отформатировать):
<%int i=0;
foreach (var review in Model.ReviewsList) { %>
<div id="review_<%=i%>">
<h3><%:review.Title%></h3>
</div>
<%i++;
} %>
Вместо этого вы можете написать:
<%foreach (var review in Model.ReviewsList.WithIndex()) { %>
<div id="review_<%=LoopHelper.Index()%>">
<h3><%:review.Title%></h3>
</div>
<%} %>
Я написал несколько вспомогательных методов, чтобы включить это:
public static class LoopHelper {
public static int Index() {
return (int)HttpContext.Current.Items["LoopHelper_Index"];
}
}
public static class LoopHelperExtensions {
public static IEnumerable<T> WithIndex<T>(this IEnumerable<T> that) {
return new EnumerableWithIndex<T>(that);
}
public class EnumerableWithIndex<T> : IEnumerable<T> {
public IEnumerable<T> Enumerable;
public EnumerableWithIndex(IEnumerable<T> enumerable) {
Enumerable = enumerable;
}
public IEnumerator<T> GetEnumerator() {
for (int i = 0; i < Enumerable.Count(); i++) {
HttpContext.Current.Items["LoopHelper_Index"] = i;
yield return Enumerable.ElementAt(i);
}
}
IEnumerator IEnumerable.GetEnumerator() {
return GetEnumerator();
}
}
В не-веб-среде вы можете использовать static
вместо HttpContext.Current.Items
.
По сути, это глобальная переменная, и поэтому вы не можете иметь более одного вложенного цикла WithIndex, но это не главная проблема в этом случае использования.