2012-06-27 2 views
3

новичок вопрос.C# общий или не общий счетчик

Массивы в C# возвращают не общий (классический) IEnumerator. Могут поставляться и другие коллекции.

Как правило, используется ли общий счетчик, если он доступен, например, по причинам безопасности типа? Бывают ли времена, когда предпочтительным является не общий вариант?

+0

Помните, что массивы были в C# 1, а generics не отображались до C# 2, поэтому было бы сложно использовать массивы (и 'ArrayList',' HashTable' и т. Д.), Чтобы вернуть их ... – AakashM

ответ

2

Обычно очень предпочтительно использовать общие перечисления, поскольку, как вы упомянули в вопросе, введите безопасность.

Не общее перечисление может быть выбором в случае, если вы храните только коллекцию объектов. Итак, вместо того, чтобы писать IEnumerable<object>, вы пишете IEnumerable и выясняете, что тип объекта внутри итерации (если вам это нужно, но обычно да) real.

1

foreach фактически не всегда используют IEnumerable[<T>]/IEnumerator[<T>] API на всех. Во-первых, она на самом деле не требуется: все, что требуется является GetEnumerator() метод, который возвращает что-то с bool MoveNext() и Current {get;} - например, List<T> имеет пользовательский итератор. Этот подход также был распространен в .NET 1.1, чтобы избежать бокса, отдавая предпочтение пользовательскому итератору.

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

static void Main() 
    { 
     foreach(var i in GetData()) Console.WriteLine(i); 
    } 
    static int[] GetData() 
    { 
     int[] data = { 1, 2, 3, 4, 5 }; 
     return data; 
    } 

Здесь Main компилируется (// комментарии мои):

.method private hidebysig static void Main() cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 i, 
     [1] int32[] CS$6$0000, 
     [2] int32 CS$7$0001) 

    // int[] arr = GetData() 
    L_0000: call int32[] ConsoleApplication7.Program::GetData() 
    L_0005: stloc.1 

    // int j = 0 
    L_0006: ldc.i4.0 
    L_0007: stloc.2 

    // run end-condition of for loop first... 
    L_0008: br.s L_0018 

    // i = arr[j] 
    L_000a: ldloc.1 
    L_000b: ldloc.2 
    L_000c: ldelem.i4   
    L_000d: stloc.0 

    // Console.WriteLine(i); 
    L_000e: ldloc.0 
    L_000f: call void [mscorlib]System.Console::WriteLine(int32) 

    // j++ 
    L_0014: ldloc.2 
    L_0015: ldc.i4.1 
    L_0016: add 
    L_0017: stloc.2 

    // j < arr.Length 
    L_0018: ldloc.2 
    L_0019: ldloc.1 
    L_001a: ldlen 
    L_001b: conv.i4 
    L_001c: blt.s L_000a 

    L_001e: ret 
} 

, который не делает никакой пользы вообще перечислителя API; он фактически реализовал его как цикл for.

Смежные вопросы