Quy tắc ẩn tên C# khá phức tạp. Ngôn ngữ cho phép bạn đề cập đến trường hợp, nhưng không cho phép nhiều trường hợp tương tự. Xem
http://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
để biết một số thông tin về chủ đề phức tạp này.
Để giải quyết câu hỏi cụ thể của bạn: trình biên dịch chắc chắn có thể phát hiện xung đột đó. Trong thực tế, nó không phát hiện mâu thuẫn:
class P
{
int x;
void M()
{
x = 123; // The author intends "this.x = 123;"
int x = 0;
}
}
C tương đương với chương trình ++ sẽ là hợp pháp C++, bởi vì trong C++ một biến địa phương đi vào phạm vi tại thời điểm kê khai. Trong C#, một biến cục bộ nằm trong phạm vi toàn bộ khối của nó, và sử dụng nó trước khi khai báo của nó là bất hợp pháp. Nếu bạn cố gắng biên soạn chương trình này bạn sẽ có được:
error CS0844: Cannot use local variable 'x' before it is declared.
The declaration of the local variable hides the field 'P.x'.
Xem: khai báo địa phương ẩn lĩnh vực.Trình biên dịch biết điều đó. Vậy tại sao trong trường hợp của bạn không phải là lỗi để ẩn trường?
Giả sử vì lý do tranh luận rằng đó phải là lỗi. Đây có phải là lỗi không?
class B
{
protected int x;
}
class D : B
{
void M()
{
int x;
}
}
Trường x là thành viên của D qua thừa kế từ B. Vì vậy, đây cũng phải là một lỗi, phải không?
Bây giờ giả sử bạn có chương trình này được sản xuất bởi Công ty Cổ phần Foo:
class B
{
}
và chương trình này được sản xuất bởi Công ty Cổ phần Bar:
class D : B
{
void M()
{
int x;
}
}
Đó biên dịch. Bây giờ giả sử Foo Corp cập nhật lớp cơ sở của họ và tàu một phiên bản mới ra với bạn:
class B
{
protected int x;
}
Bạn đang nói với tôi rằng mỗi lớp có nguồn gốc có chứa một biến địa phương tên là x bây giờ sẽ không biên dịch?
Điều đó thật kinh khủng. Chúng ta phải cho phép các biến cục bộ cho các thành viên shadow.
Và nếu chúng ta sẽ cho phép người dân địa phương để bóng thành viên của các lớp cơ sở, nó sẽ có vẻ hết sức kỳ lạ để không cho phép người dân địa phương để bóng thành viên của các lớp học.
Bạn có thể tham khảo 'x' và' this.x', vì vậy không có vấn đề gì. – Blorgbeard
Thực ra điều đó là nhất quán. nếu bạn chỉ có x = 0 trong hàm void foo() thì nó sẽ nhận biến từ x mà bạn đã định nghĩa trước đó. Bởi vì bạn có int x = 0 trong phương thức bạn có cho tất cả các ý định đã tạo ra một biến mới. Nhưng nếu bạn nhìn vào giá trị của x bên ngoài của phương pháp foo nó sẽ vẫn là 0 bởi vì bạn đang ở trong một phạm vi khác nhau sau đó. – Brian
Nếu bạn không thích có thể có một biến địa phương có cùng tên với một thành viên lớp, thì bạn có thể nhận được ReSharper và [có nó ngăn cản bạn làm điều này] (http://confluence.jetbrains.net/display/ReSharper/Local + biến + ẩn + thành viên). – AakashM