Tại sao mã này hoạt động? Tôi đang sử dụng C # 8 với Visual Studio 2019.
Bạn đã trả lời câu hỏi của riêng bạn! Đó là bởi vì bạn đang sử dụng C # 8.
Quy tắc từ C # 1 đến 7 là: một tên đơn giản không thể được sử dụng để có nghĩa là hai điều khác nhau trong cùng một phạm vi địa phương. (Quy tắc thực tế phức tạp hơn một chút so với quy tắc đó nhưng mô tả mức độ tẻ nhạt; xem thông số kỹ thuật C # để biết chi tiết.)
Mục đích của quy tắc này là để ngăn chặn loại tình huống mà bạn đang nói đến trong ví dụ của bạn, nơi nó trở nên rất dễ bị nhầm lẫn về ý nghĩa của địa phương. Đặc biệt, quy tắc này được thiết kế để ngăn ngừa những nhầm lẫn như:
class C
{
int x;
void M()
{
x = 123;
if (whatever)
{
int x = 356;
...
Và bây giờ chúng ta có một tình huống bên trong cơ thể M
, x
có nghĩa là cả this.x
và địa phương x
.
Mặc dù có thiện chí, có một số vấn đề với quy tắc này:
- Nó đã không được thực hiện để spec. Có những tình huống mà một tên đơn giản có thể được sử dụng như, cả loại và thuộc tính, nhưng chúng không phải luôn được gắn cờ là lỗi vì logic phát hiện lỗi bị sai sót. (Xem bên dưới)
- Các thông báo lỗi được diễn đạt một cách khó hiểu và được báo cáo không nhất quán. Có nhiều thông báo lỗi khác nhau cho tình huống này. Họ không nhất quán xác định người phạm tội; nghĩa là, đôi khi việc sử dụng bên trong sẽ được gọi ra, đôi khi là bên ngoài và đôi khi nó chỉ gây nhầm lẫn.
Tôi đã nỗ lực viết lại Roslyn để sắp xếp thứ này; Tôi đã thêm một số thông báo lỗi mới và làm cho các thông báo lỗi cũ nhất quán về nơi báo cáo lỗi. Tuy nhiên, nỗ lực này là quá ít, quá muộn.
Nhóm C # đã quyết định cho C # 8 rằng toàn bộ quy tắc đã gây ra nhiều nhầm lẫn hơn là ngăn chặn và quy tắc này đã bị loại bỏ khỏi ngôn ngữ. (Cảm ơn Jonathon Chase vì đã xác định thời điểm nghỉ hưu xảy ra.)
Nếu bạn muốn tìm hiểu lịch sử của vấn đề này và cách tôi cố gắng khắc phục nó, hãy xem những bài viết tôi đã viết về nó:
https://ericlippert.com/2009/11/02/simple-names-are-not-so-simple/
https://ericlippert.com/2009/11/05/simple-names-are-not-so-simple-part-two/
https://ericlippert.com/2014/09/25/ bối rối-giới thiệu-for-a-confuses-tính năng-part-one /
https://ericlippert.com/2014/09/29/confuses-errors-for-a- bối rối-tính năng-part-two /
https://ericlippert.com/2014/10/03/ bối rối-giới thiệu-for-a- bối rối-tính năng-part-three /
Cuối phần ba tôi đã lưu ý rằng còn có sự tương tác giữa tính năng này và tính năng "Màu màu" - đó là tính năng cho phép:
class C
{
Color Color { get; set; }
void M()
{
Color = Color.Red;
}
}
Ở đây chúng tôi đã sử dụng tên đơn giản Color
để chỉ cả hai this.Color
và loại liệt kê Color
; theo một cách đọc nghiêm ngặt về đặc tả kỹ thuật này sẽ là một lỗi, nhưng trong trường hợp này, thông số kỹ thuật đã sai và ý định là cho phép nó, vì mã này không rõ ràng và sẽ gây phiền toái cho nhà phát triển thay đổi nó.
Tôi chưa bao giờ viết bài báo đó mô tả tất cả các tương tác kỳ lạ giữa hai quy tắc này và bây giờ sẽ hơi vô nghĩa khi làm như vậy!
x
tham số của phương thức đó được chuyển ra khỏi phạm vi. Xem sharplab cho một ví dụ.