Tại sao C # cho phép khối mã mà không có một tuyên bố trước đó (ví dụ như if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Tại sao C # cho phép khối mã mà không có một tuyên bố trước đó (ví dụ như if
, else
, for
, while
)?
void Main()
{
{ // any sense in this?
Console.Write("foo");
}
}
Câu trả lời:
Trong bối cảnh bạn đưa ra, không có ý nghĩa. Việc ghi một chuỗi hằng vào bảng điều khiển sẽ hoạt động theo cùng một cách ở bất kỳ đâu trong luồng chương trình. 1
Thay vào đó, bạn thường sử dụng chúng để hạn chế phạm vi của một số biến cục bộ. Điều này được làm rõ hơn ở đây và ở đây . Hãy xem câu trả lời của João Angelo và câu trả lời của Chris Wallis để biết các ví dụ ngắn gọn. Tôi tin rằng điều tương tự cũng áp dụng cho một số ngôn ngữ khác có cú pháp kiểu C, không phải là chúng sẽ liên quan đến câu hỏi này.
1 Tất nhiên, trừ khi bạn quyết định cố gắng trở nên hài hước và tạo ra Console
lớp học của riêng mình , bằng một Write()
phương pháp hoàn toàn bất ngờ.
out
tham số cho một triển khai giao diện được viết bằng một ngôn ngữ khác và việc triển khai đó đọc biến trước khi viết nó.
Các { ... }
có ít nhất là tác dụng phụ của việc giới thiệu một phạm vi mới cho các biến địa phương.
Tôi có xu hướng sử dụng chúng trong các switch
câu lệnh để cung cấp phạm vi khác nhau cho từng trường hợp và theo cách này, cho phép tôi xác định biến cục bộ có cùng tên ở vị trí sử dụng chúng gần nhất có thể và cũng để biểu thị rằng chúng chỉ hợp lệ ở cấp trường hợp.
{}
việc giữ cho những huy hiệu vàng đó đến ... :)
Nó không phải là một tính năng của C # nhiều hơn nó là một tác dụng phụ hợp lý của nhiều ngôn ngữ cú pháp C sử dụng dấu ngoặc nhọn để xác định phạm vi .
Trong ví dụ của bạn, dấu ngoặc nhọn không có tác dụng gì cả, nhưng trong đoạn mã sau, chúng xác định phạm vi và do đó khả năng hiển thị, của một biến:
Điều này được cho phép vì tôi nằm ngoài phạm vi trong khối đầu tiên và được xác định lại trong phần tiếp theo:
{
{
int i = 0;
}
{
int i = 0;
}
}
Điều này không được phép vì tôi đã vượt ra khỏi phạm vi và không còn hiển thị trong phạm vi bên ngoài:
{
{
int i = 0;
}
i = 1;
}
Và vân vân.
{}
được gọi là dấu ngoặc đơn?
One of two marks of the form [ ] or ( ), and in mathematical use also {}, used for enclosing a word or number of words, a portion of a mathematical formula, or the like, so as to separate it from the context;
Trong mọi trường hợp, chúng không phải là dấu ngoặc đơn, nhưng 'dấu ngoặc nhọn' có vẻ OK.
Tôi coi {}
như một câu lệnh có thể chứa một số câu lệnh.
Hãy xem xét một câu lệnh if tồn tại ngoài một biểu thức boolean được theo sau bởi một câu lệnh. Điều này sẽ hoạt động:
if (true) Console.Write("FooBar");
Điều này cũng sẽ hoạt động:
if (true)
{
Console.Write("Foo");
Console.Write("Bar");
}
Nếu tôi không nhầm thì đây được gọi là câu lệnh khối.
Vì {}
có thể chứa các câu lệnh khác nó cũng có thể chứa các câu lệnh khác {}
. Phạm vi của một biến được xác định bởi cha của nó {}
(câu lệnh khối).
Điểm mà tôi đang cố gắng đưa ra là đó {}
chỉ là một tuyên bố, vì vậy nó không yêu cầu nếu hoặc bất cứ điều gì ...
Quy tắc chung trong các ngôn ngữ cú pháp C là "bất kỳ thứ gì ở giữa { }
phải được coi là một câu lệnh duy nhất và nó có thể đi đến bất cứ nơi nào mà một câu lệnh duy nhất có thể":
if
.for
, while
hoặc do
.Đối với tất cả các ý định và mục đích, ngữ pháp ngôn ngữ đã bao gồm điều này:
<statement> :== <definition of valid statement> | "{" <statement-list> "}"
<statement-list> :== <statement> | <statement-list> <statement>
Đó là, "một câu lệnh có thể được cấu tạo bởi (nhiều thứ khác nhau) hoặc một dấu ngoặc nhọn mở, theo sau là một danh sách câu lệnh (có thể bao gồm một hoặc nhiều câu lệnh), theo sau là một dấu ngoặc nhọn". IE "một { }
khối có thể thay thế bất kỳ câu lệnh nào, ở bất kỳ đâu". Bao gồm cả ở giữa mã.
Việc không cho phép một { }
khối ở bất kỳ đâu mà một câu lệnh đơn lẻ có thể thực sự làm cho định nghĩa ngôn ngữ trở nên phức tạp hơn .
Vì C ++ (và java) cho phép các khối mã mà không có câu lệnh trước.
C ++ cho phép chúng vì C đã làm.
Có thể nói tất cả xuất phát từ thực tế là thiết kế ngôn ngữ chương trình Hoa Kỳ (dựa trên C) đã chiến thắng hơn là thiết kế ngôn ngữ chương trình Châu Âu ( dựa trên Modula-2 ).
(Các câu lệnh điều khiển hoạt động trên một câu lệnh duy nhất, các câu lệnh có thể là nhóm để tạo ra các câu lệnh mới)
// if (a == b)
// if (a != b)
{
// do something
}
Bạn đã hỏi "tại sao" C # cho phép khối mã mà không cần câu lệnh trước. Câu hỏi "tại sao" cũng có thể được hiểu là "lợi ích có thể có của cấu trúc này là gì?"
Cá nhân tôi sử dụng các khối mã không cần câu lệnh trong C # nơi mà khả năng đọc được cải thiện đáng kể cho các nhà phát triển khác, đồng thời lưu ý rằng khối mã giới hạn phạm vi của các biến cục bộ. Ví dụ: hãy xem xét đoạn mã sau, đoạn mã này dễ đọc hơn rất nhiều nhờ các khối mã bổ sung:
OrgUnit world = new OrgUnit() { Name = "World" };
{
OrgUnit europe = new OrgUnit() { Name = "Europe" };
world.SubUnits.Add(europe);
{
OrgUnit germany = new OrgUnit() { Name = "Germany" };
europe.SubUnits.Add(germany);
//...etc.
}
}
//...commit structure to DB here
Tôi biết rằng điều này có thể được giải quyết một cách thanh lịch hơn bằng cách sử dụng các phương pháp cho từng cấp cấu trúc. Tuy nhiên, một lần nữa, hãy nhớ rằng những thứ như trình gieo dữ liệu mẫu thường cần nhanh chóng.
Vì vậy, mặc dù đoạn mã trên được thực thi một cách tuyến tính, cấu trúc mã vẫn đại diện cho cấu trúc "thế giới thực" của các đối tượng, do đó giúp các nhà phát triển khác hiểu, duy trì và mở rộng dễ dàng hơn.