Câu hỏi Tại sao C # 3 cho phép chuyển đổi ngầm của chữ số 0 (0) thành bất kỳ Enum nào?


C # 3 (Visual Studio 2008) đã giới thiệu một sự thay đổi đột phá đối với ngôn ngữ (http://msdn.microsoft.com/en-us/library/cc713578.aspx, xem thay đổi 12) cho phép bất kỳ số không bằng chữ nào được chuyển đổi hoàn toàn thành một Enum. Điều này có vẻ kỳ quặc theo nhiều cách. Có ai biết tại sao đây là một phần của spec? Tại sao không phải là một nghĩa đen? Hay bảy? Tại sao không đặc biệt? Và nó làm cho một số lựa chọn độ phân giải quá tải rất trực quan. Ví dụ.

function string F(object o) { return o.ToString(); }
function string F(DbType t) { return t.ToString(); }
int i = 0;
F((long)0) == "String" // would have been "0" in VS 2005
F(0) == "String"
F(i) == "0"

Rất khó hiểu và một sự thay đổi đột phá được giới thiệu với ngôn ngữ. Bất kỳ ý tưởng?


9
2017-10-27 19:36


gốc


Nếu bạn định thực hiện một thay đổi mạnh mẽ cho một câu hỏi (đặc biệt là câu hỏi đã được bình chọn để trả lời), thì tốt nhất - đối với người trả lời, trình duyệt và bạn - để tạo một câu hỏi mới. Bây giờ bạn sẽ có câu trả lời cho hai câu hỏi khác nhau, đầu tiên trong đó các trình duyệt thông thường có thể sẽ không bao giờ nhìn thấy trong lịch sử chỉnh sửa. - joshperry
và giống như ma thuật, câu hỏi đã được chỉnh sửa trở lại hình thức gây hiểu nhầm ban đầu của nó! nó cần phải được lưu ý rằng các mẫu được đưa ra không bị hỏng trong VS 2008. tôi sẽ thực hiện thay đổi đó và xem nếu nó gậy ... - Sebastian Good


Các câu trả lời:


C # luôn cho phép chuyển đổi ngầm của chữ 0 thành bất kỳ giá trị Enum nào. Điều gì đã thay đổi là cách quy tắc được áp dụng cho các biểu thức hằng số khác. Nó đã được thực hiện để phù hợp hơn và cho phép bất kỳ biểu thức liên tục nào đánh giá 0 được chuyển đổi hoàn toàn thành một enum.

Ví dụ bạn đã tạo ra cùng một hành vi trong tất cả các phiên bản của C #.

Dưới đây là ví dụ về hành vi đã thay đổi (trực tiếp từ tài liệu liên kết)

public enum E
{
    Zero = 0,
    One = 1,
} 

class A
{
    public static A(string s, object o)
    { System.Console.WriteLine("{0} => A(object)", s); } 

    public static A(string s, E e)
    { System.Console.WriteLine("{0} => A(Enum E)", s); }

    static void Main()
    {
        A a1 = new A("0", 0);
        A a3 = new A("(int) E.Zero", (int) E.Zero);
    }
}

Visual C # 2005 đầu ra:

0 => A (Enum E)
(int) E.Zero => A (đối tượng)

Visual C # 2008 đầu ra:

0 => A (Enum E)
(int) E.Zero => A (Enum E)

10
2017-10-27 19:44



Ah, một điểm tốt. Ví dụ từ ứng dụng của chúng tôi thực sự là nơi lập trình viên sử dụng (dài) 0. Có lẽ trong một phiên bản trước đó không kích hoạt quy tắc 'biểu thức liên tục'. Câu hỏi vẫn còn là: tại sao nếu không có số nguyên nào khác được chuyển đổi hoàn toàn thành Enum là số không? - Sebastian Good
@ Sebastian, tôi không chắc chắn về điểm này. Có lẽ một lý do ngôn ngữ rất thú vị tại sao và hy vọng Eric sẽ có mặt sau đó để bình luận về điều này. - JaredPar
Một biểu thức liên tục là bất kỳ biểu thức nào có thể được xác định tại thời gian biên dịch để dẫn đến một giá trị không đổi (giá trị của kết quả của biểu thức có thể được thay thế trong mã nguồn không có tác dụng phụ). Trong VS 2005 chỉ có "số nguyên" số không được chuyển đổi hoàn toàn thành enums, trong> = VS 2008 bất kỳ "biểu thức liên tục" nào đánh giá về 0 sẽ được chuyển đổi hoàn toàn. - joshperry


Tôi đoán đó là vì 0 được coi là "Giá trị mặc định" của enums.

C # (từ khóa mặc định được giới thiệu trong C # 2.0)

enum DbType {
    Unspecified,
    SqlServer
}

DbType t;
int i = 0;

Console.WriteLine(t == i);
Console.WriteLine(i == default(DbType));

Đầu ra:

True
True

4
2017-10-27 19:42



Tôi tưởng tượng nó khá nhiều vì default(T) đã không tồn tại trong 1.0, và họ không muốn có một mâu thuẫn trong ngôn ngữ mà bạn có thể nhận được biến enum mặc định-initialized để 0 ngầm, nhưng không rõ ràng (không có diễn viên). - Pavel Minaev
@Pavel Minaev - Tôi thích lý thuyết này. - Sebastian Good


Nó đã được cho phép từ phiên bản 1.0. Đó là giá trị mặc định của một enum.

"Một chữ số 0 được chuyển đổi hoàn toàn   cho bất kỳ loại enum nào. Trong Visual C # 2005   và các phiên bản trước của trình biên dịch,   cũng có một số hằng số   các biểu thức đánh giá là 0   có thể chuyển đổi thành bất kỳ enum nào   loại, nhưng quy tắc xác định   biểu thức nào trong số này là   chuyển đổi là không rõ ràng. Trong Visual C #   Năm 2008, tất cả các biểu thức liên tục   bằng 0 có thể ngầm   chuyển thành bất kỳ loại enum nào. "


2
2017-10-27 19:42





"Kiểu mặc định của các phần tử liệt kê là int. Theo mặc định, điều tra viên đầu tiên có giá trị 0 và giá trị của mỗi điều tra kế tiếp được tăng lên 1." - Đây là từ MSDN ghi chú cho khuôn khổ 1.1, vì vậy nó luôn luôn là trường hợp.


0
2017-10-27 19:47





Như những người khác đã đề cập, 0 là enum mặc định. Hãy thử suy nghĩ về các liệt kê như sau (theo một cách rõ ràng hơn):

public enum HairColor
{
    Blonde           = 0x0000;
    Brunett          = 0x0001;
    Red              = 0x0002;
    StrawberryBlonde = 0x0004;
}

Bởi vì bạn không được rõ ràng trong các giá trị của bạn của một liệt kê nhất định, C # sẽ tự động gán nó một giá trị mặc định. Nếu bạn không muốn điều đó, thì bạn sẽ phải xác định rõ ràng các giá trị cho một kiểu liệt kê đã cho.


0
2017-10-27 19:49