了解C#和Java上传统迭代和增强迭代的实现

本文关键字:迭代 增强 实现 Java 了解 传统 | 更新日期: 2023-09-27 17:59:43

我对C#foreachJava为增强的的工作方式感到非常困惑,更令人沮丧的是,我意识到为什么我以前没有遇到过这个细节。

但无论如何,事实是,我真的很想理解为什么这些看似相似的流控制语句的工作方式如此不同。为了便于说明,我们假设我们需要遍历一个整数数组,两种实现都类似于:

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

了解C#和Java上传统迭代和增强迭代的实现

在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 !!

您将该值用作索引器,foreach会为您提供数组中的每个值,而不是每个索引

如果你写

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

它应该是正确的

不确定我是应该将其作为注释添加到Carson63000还是作为答案添加,但Java也有同样的问题。

for(int i:foobar)

 nbsp nbsp 系统输出打印(i)
}

顺便说一句,我发现Java的"enhanced for"不如C#的foreach直观。我认为,在处理Java之后,您开始理解"for(inti:foobar)"的含义,但我认为没有人会认为foreach更简单。

不过,在使用for循环时,foreach和"enhanced for"有时不是最佳选择。如果您需要访问数组中的多个值,最好使用传统的for循环,因为foreach/enhanced for一次只能访问一个值。