Trong C# 5, ngữ nghĩa đóng của câu lệnh foreach
(khi biến lặp được "bắt" hoặc "đóng cửa" bởi các hàm ẩn danh) là famously changed (link to thread on that topic).Ngữ nghĩa đóng cửa để tìm kiếm trên các mảng kiểu con trỏ
Câu hỏi: Có ý định thay đổi điều này cho các mảng kiểu con trỏ không?
Lý do tại sao tôi hỏi là "bành trướng" của một tuyên bố foreach
phải được viết lại, vì lý do kỹ thuật (chúng tôi không thể sử dụng Current
tài sản của System.Collections.IEnumerator
từ khách sạn này đã tuyên bố loại object
mà không tương thích với một con trỏ loại) so với foreach
so với các bộ sưu tập khác. Các phần có liên quan trong C# Language Specification, "Pointer mảng", trong phiên bản 5,0, nói rằng:
foreach (V v in x) EMBEDDED-STATEMENT
được mở rộng để:
{
T[,,…,] a = x;
V v;
for (int i0 = a.GetLowerBound(0); i0 <= a.GetUpperBound(0); i0++)
for (int i1 = a.GetLowerBound(1); i1 <= a.GetUpperBound(1); i1++)
…
for (int in = a.GetLowerBound(N); iN <= a.GetUpperBound(n); iN++) {
v = (V)a.GetValue(i0,i1,…,iN);
EMBEDDED-STATEMENT
}
}
Chúng tôi lưu ý rằng việc kê khai V v;
là bên ngoài tất cả các vòng for
. Vì vậy, nó sẽ xuất hiện rằng ngữ nghĩa đóng cửa vẫn là "cũ" hương vị C# 4, "biến vòng lặp được tái sử dụng, biến vòng lặp là" bên ngoài "đối với vòng lặp".
Để làm cho nó rõ ràng những gì tôi đang nói về, hãy xem xét hoàn thành chương trình này C# 5:
using System;
using System.Collections.Generic;
static class Program
{
unsafe static void Main()
{
char* zeroCharPointer = null;
char*[] arrayOfPointers =
{ zeroCharPointer, zeroCharPointer + 1, zeroCharPointer + 2, zeroCharPointer + 100, };
var list = new List<Action>();
// foreach through pointer array, capture each foreach variable 'pointer' in a lambda
foreach (var pointer in arrayOfPointers)
list.Add(() => Console.WriteLine("Pointer address is {0:X2}.", (long)pointer));
Console.WriteLine("List complete");
// invoke those delegates
foreach (var act in list)
act();
}
// Possible output:
//
// List complete
// Pointer address is 00.
// Pointer address is 02.
// Pointer address is 04.
// Pointer address is C8.
//
// Or:
//
// List complete
// Pointer address is C8.
// Pointer address is C8.
// Pointer address is C8.
// Pointer address is C8.
}
Vì vậy, đầu ra chính xác của chương trình trên là gì?
Chú ý: Việc mở rộng trên có một vấn đề rõ ràng ở chỗ nó viết 'a.GetValue (i0, i1, ..., iN) 'nơi' GetValue' dường như được phương pháp này được xác định bởi' hệ thống .Array'. Nhưng phương thức đó có giá trị trả về 'đối tượng', vì vậy nó không thể được sử dụng cho các kiểu con trỏ. Vì vậy, thông số C# không thành công trong việc tránh _ "bất kỳ nỗ lực nào để truy cập các phần tử mảng thông qua' System.Array' "_, để trích dẫn chính C# spec. Có lẽ đó phải là 'a [i0, i1,…, iN]' trong đó khung '[…]' được định nghĩa bởi phần con _ "Truy cập phần tử mảng" _. Hãy thử nói 'arrayOfPointers.GetValue (0)' cho mình, trong mẫu mã trên. –