Tôi đã viết mã này:
private static Expression<Func<Binding, bool>> ToExpression(BindingCriterion criterion)
{
switch (criterion.ChangeAction)
{
case BindingType.Inherited:
var action = (byte)ChangeAction.Inherit;
return (x => x.Action == action);
case BindingType.ExplicitValue:
var action = (byte)ChangeAction.SetValue;
return (x => x.Action == action);
default:
// TODO: Localize errors
throw new InvalidOperationException("Invalid criterion.");
}
}
Và rất ngạc nhiên khi tìm thấy một lỗi biên dịch:
Một biến cục bộ có tên 'hành động' đã được xác định trong phạm vi này
Đó là một vấn đề khá dễ dàng để giải quyết; chỉ cần thoát khỏi thứ hai var
đã lừa
Rõ ràng các biến được khai báo trong case
các khối có phạm vi của cha mẹ switch
, nhưng tôi tò mò về lý do tại sao điều này là. Cho rằng C # không cho phép thực hiện giảm thông qua các trường hợp khác (nó đòi hỏi break
, return
, throw
, hoặc goto case
báo cáo vào cuối mỗi case
khối), nó có vẻ khá kỳ lạ mà nó sẽ cho phép khai báo biến bên trong một case
được sử dụng hoặc mâu thuẫn với các biến trong bất kỳ khác case
. Nói cách khác, các biến dường như rơi vào các case
câu lệnh mặc dù thực thi không thể. C # rất đau đớn để thúc đẩy khả năng đọc bằng cách cấm một số cấu trúc của các ngôn ngữ khác gây nhầm lẫn hoặc dễ bị lạm dụng. Nhưng điều này có vẻ như nó chỉ bị ràng buộc để gây nhầm lẫn. Hãy xem xét các tình huống sau:
Nếu được thay đổi nó thành này:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: return (x => x.Action == action);
Tôi nhận được " Sử dụng biến cục bộ chưa được gán 'hành động' ". Điều này gây nhầm lẫn bởi vì trong mọi cấu trúc khác trong C # mà tôi có thể nghĩ
var action = ...
sẽ khởi tạo biến, nhưng ở đây nó chỉ đơn giản là khai báo nó.Nếu tôi đã trao đổi các trường hợp như thế này:
case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; return (x => x.Action == action); case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action);
Tôi nhận được " Không thể sử dụng biến cục bộ 'hành động' trước khi nó được khai báo ". Vì vậy, thứ tự của các khối trường hợp dường như rất quan trọng ở đây theo cách không hoàn toàn rõ ràng - Thông thường tôi có thể viết chúng theo bất kỳ thứ tự nào tôi muốn, nhưng vì
var
phải xuất hiện trong khối đầu tiênaction
được sử dụng, tôi phải điều chỉnhcase
các khối phù hợp.Nếu được thay đổi nó thành này:
case BindingType.Inherited: var action = (byte)ChangeAction.Inherit; return (x => x.Action == action); case BindingType.ExplicitValue: action = (byte)ChangeAction.SetValue; goto case BindingType.Inherited;
Sau đó, tôi không nhận được lỗi, nhưng theo một nghĩa nào đó, có vẻ như biến đang được gán một giá trị trước khi nó được khai báo.
(Mặc dù tôi không thể nghĩ về bất cứ lúc nào bạn thực sự muốn làm điều này - tôi thậm chí không biếtgoto case
đã tồn tại trước ngày hôm nay)
Vì vậy, câu hỏi của tôi là, tại sao các nhà thiết kế của C # không đưa ra case
phạm vi địa phương của riêng họ? Có bất kỳ lý do lịch sử hoặc kỹ thuật cho việc này?
switch
chút nào - Tôi chỉ tò mò về lý do đằng sau thiết kế này.
break
là không thể xảy ra trong C #.
action
biến của bạn trướcswitch
câu lệnh hoặc đặt từng trường hợp vào dấu ngoặc nhọn của chính nó và bạn sẽ có hành vi hợp lý.