Vòng lặp foreach trong lập trình C# cơ bản

Dẫn nhập

Ở các bài học trước, chúng ta đã cùng nhau tìm hiểu về MẢNG NHIỀU CHIỀU TRONG C#. Hôm nay chúng ta sẽ cùng tìm hiểu về cấu trúc lặp foreach trong C#.

Nội dung

Để đọc hiểu bài này tốt nhất những bạn nên có kiến thức và kỹ năng cơ bản về những phần :

Trong bài học này, chúng ta sẽ cùng tìm hiểu các vấn đề:

  • Cú pháp và nguyên tắc hoạt động của foreach trong C#
  • Sử dụng foreachtrong C#
  • So sánh for và foreachtrong C#

Cú pháp và nguyên tắc hoạt động của foreach trong C#

Cấu trúc lặp foreach cho phép chúng ta duyệt 1 mảng hoặc 1 tập hợp (sẽ được trình bày trong bài TỔNG QUAN VỀ COLLECTION TRONG C#).

Một số đặc trưng của foreach :

  • Foreach không duyệt mảng hoặc tập hợp thông qua chỉ số phần tử như cấu trúc lặp for.
  • Foreach duyệt tuần tự các phần tử trong mảng hoặc tập hợp.
  • Foreach chỉ dùng để duyệt mảng hoặc tập hợp ngoài ra không thể làm gì khác.

Cú pháp

foreach ( in)

{
/ / Code giải quyết và xử lý
}

Trong đó :

  • Các từ khoá foreach, in là từ khoá bắt buộc.
  • là kiểu dữ liệu của các phần tử trong mảng hoặc tập hợp.

  • là tên 1 biến tạm đại diện cho phần tử đang xét khi duyệt mảng hoặc tập hợp.

  • là tên của mảng hoặc tập hợp cần duyệt.

Nguyên tắc hoạt động

Foreach cũng có nguyên tắc hoạt động tương tự như các cấu trúc lặp khác cụ thể như sau:

  • Ở vòng lặp đầu tiên sẽ gán giá trị của phần tử đầu tiên trong mảng vào biến tạm.
  • Thực hiện khối lệnh bên trong vòng lặp foreach.
  • Qua mỗi vòng lặp tiếp theo sẽ thực hiện kiểm tra xem đã duyệt hết mảng hoặc tập hợp chưa. Nếu chưa thì tiếp gán giá trị của phần tử hiện tại vàobiến tạmvà tiếp tục thực hiện khối lệnh bên trong.
  • Nếu đã duyệt qua hết các phần tử thì vòng lặp sẽ kết thúc.

Qua nguyên tắc hoạt động giải trí trên ta hoàn toàn có thể thấy :

  • Biến tạm trong vòng lặp foreach sẽ tương đương với phần tử i trong cách duyệt của vòng lặp for(đã trình bày trong bài CẤU TRÚC VÒNG LẶP FOR TRONG C#).
  • Qua mỗi bước lặp ta chỉ có thể thao tác với giá trị của phần tử đang xét mà không thể tương tác với các phần tử đứng trước nó hay đứng sau nó (trong CẤU TRÚC VÒNG LẶP FOR TRONG C# thì hoàn toàn được).
  • Bằng cách duyệt của foreachta không thể thay đổi giá trị của các phần tử vì lúc này giá trị của nó đã được sao chép ra một 1 biến tạm và ta chỉ có thể thao tác với biến tạm.
  • Thậm chí việc thay đổi giá trịcủabiến tạm cũng không được phép. Nếu ta cố làm điều đó thì sẽ gặp lỗi sau:

Vòng lặp foreach trong C#,  C# cơ bản, tự học C#, Kteam, HowKteam

Sử dụng foreach trong C#

Trong C#, có những danh sách, tập hợp mà ta không thể truy xuất đến các phần tử của nó thông qua chỉ số phần tử được (ví dụ như kiểu List – sẽ được trình bày trong bài LIST TRONG C# hoặc các collection, generic – sẽ được trình bày trong bài COLLECTION TRONG C# và bài GENERIC TRONG C#).

Trong trường hợp như vậy, để duyệt những list, tập hợp có đặc thù như trên thì foreach là lựa chọn tốt nhất .
Chúng ta sẽ tìm hiểu và khám phá sức mạnh của foreach qua những bài học kinh nghiệm sau. Còn trong bài học kinh nghiệm này mình chỉ ví dụ đơn thuần để những bạn hoàn toàn có thể nắm cú pháp cũng như cách sử dụng foreach .

  •  Xét chương trình sau:
/*
             * Khai báo mảng 1 chiều IntArray và khởi tạo giá trị.
             * Các bạn có thể xem lại cú pháp này ở bài Mảng 1 chiều trong C#
             * Khai báo 1 biến Sum để chứa giá trị tổng các phần tử trong mảng IntArray.
             */
            int[] IntArray = { 1, 5, 2, 4, 6 };
            int Sum = 0;

            /*
             * Sử dụng foreach để duyệt mảng và in giá trị của các phần tử trong mảng.
             * Đồng thời tận dụng vòng lặp để tính tổng các phần tử trong mảng.
             */
            foreach (int item in IntArray)
            {
                Console.Write("\t" + item);
                Sum += item;
            }

            Console.WriteLine("\n Sum = " + Sum);

Có lẽ tất cả chúng ta đã không mấy lạ lẫm với đoạn chương trình trên. Đoạn chương trình trên sẽ duyệt mảng để in ra những giá trị của mảng và tính tổng những thành phần trong mảng .

Nhưng thay vì sử dụng for thì mình sử dụng foreach để các bạn có thể thấy được sự tương đồng giữa các thành phần trong cấu trúc foreach và CẤU TRÚC VÒNG LẶP FOR TRONG C#.

Kết quả khi chạy đoạn chương trình trên :

Vòng lặp foreach trong C#,  C# cơ bản, tự học C#, Kteam, HowKteam

Ví dụ thứ 2: ta thử sử dụng foreach để duyệt mảng jagged

/*
             * Khai báo 1 mảng jagged tên là JaggedArray và khởi tạo giá trị.
             * Các bạn có thể xem lại cú pháp khai báo này ở bài Mảng nhiều chiều trong C#.
             */
            int[][] JaggedArray = 
                            { 
                                new int[] { 1, 2, 3 },
                                new int[] { 5, 2, 4, 1, 6},
                                new int[] { 7, 3, 4, 2, 1, 5, 9, 8}
                            };

            /*
             * Tương tự như dùng for, ta cũng dùng 2 vòng foreach lồng vào nhau để duyệt mảng.
             */
            foreach (int[] Element in JaggedArray)
            {
                foreach (int item in Element)
                {
                    Console.Write(item + "  ");
                }
                Console.WriteLine();
            }

Ta hoàn toàn có thể thấy cách duyệt foreach ngắn gọn hơn nhiều so với cách duyệt bằng vòng lặp for thường thì .
Ta cũng chả chăm sóc đến việc phải giải quyết và xử lý độ dài mảng hay chỉ số thành phần để truy xuất 1 thành phần nào đó .

  • Kết quả khi chạy đoạn chương trình trên:

Vòng lặp foreach trong C#,  C# cơ bản, tự học C#, Kteam, HowKteam

So sánh for và foreach trong C#

Foreach mang trong mình một số ưu điểm như:

  • Câu lệnh ngắn gọn, sẽ sử dụng.
  • Rất có ích khi duyệt danh sách, tập hợp mà không thể truy xuất thông qua chỉ số phần tử.
  • Duyệt các danh sách, tập hợp có số phần tử không xác định hoặc số phần tử thay đổi liên tục.

Mặc dù có nhiều ưu điểm nhưng không hẳn là foreach hơn hẵn for. Cùng điểm qua một vài tiêu chuẩn để xem 2 đối thủ cạnh tranh này ai hơn ai nhé .
Tiêu chí
For
Foreach
Khả năng truy xuất thành phần
Truy xuất ngẫu nhiên ( hoàn toàn có thể gọi bất kể thành phần nào trong mảng để sử dụng )
Truy xuất tuần tự ( chỉ sử dụng được giá trị thành phần đang xét )
Thay đổi được giá trị của những thành phần

Không
Duyệt mảng, tập hợp khi không biết được số thành phần của mảng, tập hợp
Không

Hiệu suất ( vận tốc giải quyết và xử lý ) ( * )
Đối với mảng, list hoặc tập hợp có năng lực truy xuất ngẫu nhiên thì for sẽ chiếm lợi thế
Đối với mảng, list hoặc tập hợp không có năng lực truy xuất ngẫu nhiên thì foreach chiếm lợi thế

( * ) Nhìn chung hiệu suất của for và foreach còn nhờ vào vào cấu trúc tài liệu đang xét do đó việc so sánh này chỉ mang đặc thù tìm hiểu thêm .

Sau đây là 2 đoạn chương trình kiểm tra tốc độ của for và foreach đối với 2 cấu trúc dữ liệu là mảng 1 chiều (có khả năng truy xuất ngẫu nhiên) và danh sách liên kết LinkedList (không có khả năng truy xuất ngẫu nhiên):

Đầu tiên là mảng 1 chiều:

/* Kiểm tra tốc độ của for */

/*
             * Sử dụng 1 cái đồng hồ để đo thời gian chạy của 2 vòng lặp for và foreach
             * Ở đây mình chỉ kiểm tra tốc độ chứ không tập trung giải thích cú pháp
             * Các bạn có thể tìm hiểu thêm.
             */
            Stopwatch start = new Stopwatch();
            start.Start();

            int[] IntArray = new int[Int32.MaxValue / 100];
            int s = 0;
            int Length = IntArray.Length;
            for (int i = 0; i < Length; i++)
            {
                s += IntArray[i];
            }

            start.Stop();
            Console.WriteLine(" Thoi gian chay cua for: {0} giay {1} mili giay", start.Elapsed.Seconds, start.Elapsed.Milliseconds);

            /* Kiểm tra tốc độ của foreach */
            Stopwatch start2 = new Stopwatch();
            start2.Start();

            int[] IntArray2 = new int[Int32.MaxValue / 100];
            int s2 = 0;

            foreach (int item in IntArray2)
            {
                s2 += item;
            }

            start2.Stop();
            Console.WriteLine(" Thoi gian chay cua foreach: {0} giay {1} mili giay", start2.Elapsed.Seconds, start2.Elapsed.Milliseconds);

  •  Đoạn chương trình mình thực hiện:
    • Khai báo 1 mảng 1 chiều có 20 triệu phần tử (khai báo số phần tử lớn để có thể thấy được sự chêch lệch về tốc độ)
    • Lần lượt dùng for, foreachđể duyệt mảng đó và thực hiện 1 câu lệnh nào đó.
    • Cuối cùng là xuất ra thời gian thực thi của từng trường hợp dưới dạng giây và mili giây.
  •  Kết quả khi chạy đoạn chương trình trên:

Vòng lặp foreach trong C#,  C# cơ bản, tự học C#, Kteam, HowKteam

  •  Dựa vào kết quả ta có thể thấy được sự chêch lệch nhỏ về tốc độ, nếu kiểm tra với số phần tử lớn hơn hoặc cấu trúc dữ liệu phức tạp hơn thì chêch lệch này càng lớn.

Tiếp theo là đến danh sách liên kết LinkedList:

/*
             * Khai báo 1 LinkedList chưa các số nguyên int và khởi tạo giá trị cho nó.
             */
            LinkedList list = new LinkedList();

            for (int i = 0; i < 100000; i++)
            {
                list.AddLast(i);
            }

	/* Kiểm tra tốc độ của for */
            Stopwatch st = new Stopwatch();
            int s1 = 0, length = list.Count;
            st.Start();
            for (int i = 0; i < length; i++)
            {
                /*
                 * Vì LinkedList không thể truy xuất thông qua chỉ số phần tử
                 * nên mình phải sử dụng 1 phương thức hỗ trợ làm điều này.
                 * Và đây chính là sự hạn chế của for đối với các cấu trúc dữ liệu tương tự như danh sách liên kết này.
                 */
                s1 += list.ElementAt(i);
            }
            st.Stop();

	/* Kiểm tra tốc độ của foreach */
            Stopwatch st2 = new Stopwatch();
            int s2 = 0;
            st2.Start();
            foreach (int item in list)
            {
                /*
                 * Vì foreach không quan tâm đến chỉ số phần tử nên code viết rất ngắn gọn
                 */
                s2 += item;
            }
            st2.Stop();

            /* In ra giá trị tính tổng giá trị các phần tử khi duyệt bằng for và foreach để chắc chắn rằng cả 2 đều chạy đúng */
            Console.WriteLine(" s1 = {0}   s2 = {1}", s1, s2);
            Console.WriteLine(" Thoi gian chay cua for = {0} giay {1} mili giay", st.Elapsed.Seconds, st.Elapsed.Milliseconds);
            Console.WriteLine(" Thoi gian chay cua foreach = {0} giay {1} mini giay", st2.Elapsed.Seconds, st2.Elapsed.Milliseconds);

  •  Chương trình mình thực hiện:
    • Tạo 1

      LinkedList

      và thêm vào 100000 phần tử.

    • Sau đó lần lượt dùng for, foreachduyệt

      LinkedList

      trên và tính tổng giá trị các phần tử trong mảng.

    • Cuối cùng in ra thời gian chạy của for, foreach.
  •  Kết quả khi chạy chương trình trên là:

Vòng lặp foreach trong C#,  C# cơ bản, tự học C#, Kteam, HowKteam

  •  Dựa vào kết quả chạy ta thấy sự chênh lệch là quá lớn, rõ ràng đối với cấu trúc dữ liệu phức tạp, không hỗ trợ truy xuất thông qua chỉ số phần tử nữa thì foreach chiếm ưu thế.

Tuỳ vào từng trường hợp mà ta nên dùng for hay foreach. Không nên lạm dụng 1 thứ quá nhiều.

Kết luận

Nội dung bài này giúp những bạn nắm được :

  • Cú pháp củaforeachtrong C#.
  • Sử dụng foreachtrong C#.
  • So sánh forvà foreachtrong C#.

Bài sau chúng ta sẽ tìm hiểu về LỚP STRING TRONG C#.

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để phát triển bài viết tốt hơn. Đừng quên “Luyện tập – Thử thách – Không ngại khó”.

Thảo luận

Nếu bạn có bất kể khó khăn vất vả hay vướng mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI và ĐÁP trên thư viện Howkteam. com để nhận được sự tương hỗ từ hội đồng .

5/5 - (1 vote)

Bài viết liên quan

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments