C# лучше, чтобы инициализировать список затем цикл по нему или просто инициализировать в условии цикла?

Я заканчиваю с большим количеством кода как это:

List<string> dates = someMethodCall();
foreach (string dateStr in dates) { }

Я обычно объявляю объект, по которому я выполняю итерации и затем использую его в foreach условие из беспокойства это someMethodCall() произошел бы для каждого повторения цикла. Имеет место это? Я предпочел бы делать это:

foreach (string dateStr in someMethodCall()) { }

Но я только хочу сделать это если someMethodCall() происходит только однажды, и затем его результаты кэшируются для каждого последующего повторения.

6
задан Sarah Vessels 25 January 2010 в 21:15
поделиться

5 ответов

Метод будет называться только один раз в обоих случаях.

Первый метод имеет преимущество читаемости, поскольку вы можете назвать переменную и описывать, что в нем с его именем. Это сделает код более самодоступным и улучшает ремонтопригодность.


Чтобы процитировать авторитетный источник по этому поводу:

Спецификация языка C # - 8.8.4. Выход Foreach

  Foreach (V v в X) встроенный оператор
 

затем расширяется до:

 {
  E e = ((c) (x)). Getnumerator ();
  пытаться {
  V v;
  в то время как (e.movenext ()) {
  v = (v) (t) e.current;
  Встроенное заявление
  }
  }
  наконец {
  ... // утилизировать e
  }
 }
 

Понятно, что выражение x в вышеупомянутом выступлении оценивается только один раз в расширении.

14
ответ дан 8 December 2019 в 04:52
поделиться

Мой подход похож на Адриан. Однако в моем случае контроллер никогда не работает с типами бетона зрения. Контроллер полностью отделен видом - таким же образом, как просмотраModel.

Как эти работы можно увидеть в примере просмотра моделя Framework WPF Framework (WAF) .

.

С наилучшими пожеланиями,

JBE

-121--1001609-

Foreach Оценка сбора будет оценивать коллекцию один раз, получить итератор, а затем использовать это для его итерации.

8
ответ дан 8 December 2019 в 04:52
поделиться

Кроме того, я не уверен, что является вашим применением, но если вы беспокоитесь о количестве кода, лямбдас может помочь убрать в некоторых случаях.

Например, если вы пишете SOREACH заявления, чтобы просто искать определенные элементы списка, рассмотрите возможность использования лямбда. Я обнаружил, что используя их, когда это уместно, уменьшило количество кода, которое я написал и сделал его более читаемым в определенных ситуациях.

1
ответ дан 8 December 2019 в 04:52
поделиться

Один из способов запомнить, как это работает, чтобы рассмотреть это: итератор не будет работать, если он продолжат вызывать ваш метод снова и снова.

Ваш метод возвращает список элементов. Если цикл продолжал вызывать свой метод снова и снова, он будет (запрещать побочные эффекты), продолжайте возвращаться таким же списком. Как будет знать цикл, на втором звонке, что он уже обработал первый элемент в списке?

Все, что вы можете перечислить, имеет метод Getnumerator () , который должен вернуть тип ( Обычно тип реализации IEnumerator, , но это не должно быть ). Возвращенный тип должен иметь текущее свойство и метод MOVENEXT () .

Возвращенный тип - это ваш объект enumerator, и ваша петля Foreach содержит ссылку на , что объект перечисления , как он перечисляет. Он продолжает вызывать тока и и MOVENEXT () на этом объекте enumerator до MOVENEXT () возвращает false.

Использование Foreach , как правило, более читаемо и удобно, но вы также можете перечислять «вручную», если хотите:

List<string> dates = someMethodCall();
IEnumerator<string> myEnumerator = dates.GetEnumerator();
while (myEnumerator.MoveNext())
{
    // do something with myEnumerator.Current
}
1
ответ дан 8 December 2019 в 04:52
поделиться

Я не самый лучший в чтении MSIL, но я сделал некоторые тестирования, и, похоже, согласны с тем, что все говорят: коллекция восхищает только один раз. См. Ниже для MSIL, если вам интересно.

public static void ATest() {
    foreach (string s in GetSomeStrings()) {
        Console.WriteLine(s);
    }
}
public static void BTest() {
    string[] strings = GetSomeStrings();

    foreach (string s in strings) {
        Console.WriteLine(s);
    }
}
public static string[] GetSomeStrings() {
    return new string[] {
        "string1", "string2", "string3"
    };
}

ATEST () MSIL:

.method public hidebysig static void ATest() cil managed
{
    .maxstack 2
    .locals init (
        [0] string s,
        [1] string[] CS$6$0000,
        [2] int32 CS$7$0001,
        [3] bool CS$4$0002)
    L_0000: nop 
    L_0001: nop 
--->L_0002: call string[] EdProgAppData_BLL.Common::GetSomeStrings()
    L_0007: stloc.1 
    L_0008: ldc.i4.0 
    L_0009: stloc.2 
    L_000a: br.s L_001d
    L_000c: ldloc.1 
    L_000d: ldloc.2 
    L_000e: ldelem.ref 
    L_000f: stloc.0 
    L_0010: nop 
    L_0011: ldloc.0 
    L_0012: call void [mscorlib]System.Console::WriteLine(string)
    L_0017: nop 
    L_0018: nop 
    L_0019: ldloc.2 
    L_001a: ldc.i4.1 
    L_001b: add 
    L_001c: stloc.2 
    L_001d: ldloc.2 
    L_001e: ldloc.1 
    L_001f: ldlen 
    L_0020: conv.i4 
    L_0021: clt 
    L_0023: stloc.3 
    L_0024: ldloc.3 
    L_0025: brtrue.s L_000c
    L_0027: ret 
}

BTEST () MSIL:

.method public hidebysig static void BTest() cil managed
{
    .maxstack 2
    .locals init (
        [0] string[] strings,
        [1] string s,
        [2] string[] CS$6$0000,
        [3] int32 CS$7$0001,
        [4] bool CS$4$0002)
    L_0000: nop 
--->L_0001: call string[] EdProgAppData_BLL.Common::GetSomeStrings()
    L_0006: stloc.0 
    L_0007: nop 
    L_0008: ldloc.0 
    L_0009: stloc.2 
    L_000a: ldc.i4.0 
    L_000b: stloc.3 
    L_000c: br.s L_001f
    L_000e: ldloc.2 
    L_000f: ldloc.3 
    L_0010: ldelem.ref 
    L_0011: stloc.1 
    L_0012: nop 
    L_0013: ldloc.1 
    L_0014: call void [mscorlib]System.Console::WriteLine(string)
    L_0019: nop 
    L_001a: nop 
    L_001b: ldloc.3 
    L_001c: ldc.i4.1 
    L_001d: add 
    L_001e: stloc.3 
    L_001f: ldloc.3 
    L_0020: ldloc.2 
    L_0021: ldlen 
    L_0022: conv.i4 
    L_0023: clt 
    L_0025: stloc.s CS$4$0002
    L_0027: ldloc.s CS$4$0002
    L_0029: brtrue.s L_000e
    L_002b: ret 
}
0
ответ дан 8 December 2019 в 04:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: