Понимание реализации традиционных и расширенных итераций на C # и Java - PullRequest
0 голосов
/ 20 июня 2011

Я чувствую себя довольно смущенным из-за того, что C # и foreach и Java * улучшены для работы, и еще более неприятно Поймите, почему я раньше не сталкивался с этой деталью.

Но в любом случае, дело в том, что я действительно хотел бы понять, почему эти, по-видимому, похожие операторы управления потоком работают так по-разному. В целях иллюстрации давайте предположим, что нам нужно перебрать массив целых чисел, причем обе реализации будут выглядеть примерно так:

C # 4.0 (код)

class Program
{
    public static void Main(string[] args)
    {
        int[] foobar = new int[] {0, 1, 1, 2, 3, 5, 8, 13, 21};
        Console.WriteLine(String.Format("[DEBUG] type: {0}", foobar.GetType()));
        Console.WriteLine(String.Format("[DEBUG] length: {0}", foobar.Length));
        try
        {
            for (int i = 0; i < foobar.Length; i++)
            {
                Console.Write(String.Format("{0} ", foobar[i]));
            }
            Console.Write(Environment.NewLine);

            foreach (var i in foobar) {
                Console.Write(String.Format("{0} ", foobar[i]));
            }
        }
        catch (Exception exception)
        {
            Console.Write(Environment.NewLine);
            Console.WriteLine(exception.ToString());
        }
        finally
        {
            Console.Write(Environment.NewLine);
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

C # 4.0 (выход)

[DEBUG] type: System.Int32[]
[DEBUG] length: 9
0 1 1 2 3 5 8 13 21
0 1 1 1 2 5 21
System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at Dotnet.Samples.Sandbox.Program.Main(String[] args) in e:\My Dropbox\Work\P
rojects\scm\git\sandbox\Dotnet.Samples.Sandbox\Dotnet.Samples.Sandbox\Program.cs
:line 51

Press any key to continue . . .

JAVA SE6 (код)

class Program {
    public static void main(String[] args) {
        int[] foobar = new int[] {0, 1, 1, 2, 3, 5, 8, 13, 21};
        System.out.println("[DEBUG] type: " + (foobar.getClass().isArray() ? "Array " : "") +  foobar.getClass().getComponentType());
        System.out.println("[DEBUG] length: " + foobar.length);
        try {    
            for (int i = 0; i < foobar.length; i++)
            {
                System.out.print(String.format("%d ", foobar[i]));
            }
            System.out.print(System.getProperty("line.separator"));
            for (int i : foobar) {
                System.out.print(String.format("%d ", foobar[i]));
            }
        } catch (Exception e) {
            System.out.print(System.getProperty("line.separator"));
            System.out.println(e.toString());
        }
    }
}

JAVA SE6 (выход)

[DEBUG] type: Array int
[DEBUG] length: 9
0 1 1 2 3 5 8 13 21 
0 1 1 1 2 5 21 
java.lang.ArrayIndexOutOfBoundsException: 13

Ответы [ 3 ]

8 голосов
/ 20 июня 2011

В версии C # ..

foreach (var i in foobar)
{
    Console.Write(String.Format("{0} ", foobar[i]));
}

.. должно быть ..

foreach (var i in foobar)
{
    Console.Write(String.Format("{0} ", i));
}

Выполнение foreach над массивом целых чисел, как и вы, не перебирает индексы массива: оно перебирает целые числа.

Учитывая массив ..

int[] foobar = new int[] {0, 1, 1, 2, 3, 5, 8, 13, 21};

.. ваш код был:

Printing element 0: 0
Printing element 1: 1
Printing element 1: 1
Printing element 2: 1
Printing element 3: 2
Printing element 5: 5
Printing element 8: 21
Printing element 13: IndexOutOfRangeException !!
4 голосов
/ 20 июня 2011

Вы используете значение в качестве индексатора, foreach дает вам каждое значение в массиве, а не каждый индекс

, если вы пишете

   foreach (var i in foobar) {
        Console.Write(String.Format("{0} ", i));
    }

, оно должно быть правильным

1 голос
/ 20 июня 2011

Не уверен, стоит ли добавить это в качестве комментария к Carson63000 или добавить в качестве ответа, но Java имеет ту же проблему.

для (int i: foobar)
{
System.out.print (я);
}

В качестве примечания я нахожу, что Java "for for" менее интуитивен, чем foreach в C #. Я думаю, что после того, как вы разберетесь с Java, вы начнете понимать, что означает «for (int i: foobar)», но я не думаю, что кто-либо станет утверждать, что foreach более прост.

Бывают случаи, когда foreach и «расширенный для» не лучший выбор при использовании цикла for. Если вам нужен доступ к более чем одному значению в массиве, лучше всего использовать традиционный цикл for, потому что foreach / extended for позволит вам получить доступ только к одному значению за раз.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...