2013-08-09 39 views
10

Trong C#, nếu chúng tôi xác định enum có chứa thành viên tương ứng với giá trị âm và sau đó chúng tôi lặp qua các giá trị của enum, giá trị âm không đến trước, nhưng cuối cùng. Tại sao điều đó lại xảy ra? Trong các ngôn ngữ khác (C, C++, Ada, v.v.), lặp lại qua một số enum sẽ cung cấp cho bạn thứ tự mà bạn đã xác định nó.Tại sao các thành viên enum phủ định được liệt kê cuối cùng bởi foreach?

MSDN có tốt example of this behavior:

using System; 

enum SignMagnitude { Negative = -1, Zero = 0, Positive = 1 }; 

public class Example 
{ 
    public static void Main() 
    { 
     foreach (var value in Enum.GetValues(typeof(SignMagnitude))) 
     { 
      Console.WriteLine("{0,3}  0x{0:X8}  {1}", 
           (int) value, ((SignMagnitude) value)); 
     } 
    } 
} 

// The example displays the following output: 
//   0  0x00000000  Zero 
//   1  0x00000001  Positive 
//  -1  0xFFFFFFFF  Negative 
+2

Có thể nó đang được sắp xếp là chưa ký. – SLaks

+4

Bạn đã thực hiện nó [* một * bước xa hơn nhiều lập trình viên] (http://stackoverflow.com/questions/18095665/a-lambda-expression-with-a-statement-body-cannot-be-converted-to-an -expression-t/18095816 # comment26488750_18095816) bằng cách tạo tài liệu. Lần sau, đọc nó: "Các phần tử của mảng được sắp xếp theo giá trị nhị phân của hằng số liệt kê (** có nghĩa là, bởi cường độ không dấu **)." – jason

+0

Từ cùng một [MSDN] (http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx) bài viết: "Các phần tử của mảng được sắp xếp theo giá trị nhị phân của hằng số liệt kê (nghĩa là, bởi cường độ không dấu của họ). " – natenho

Trả lời

15

Từ the very documentation page you link to, tôi nhấn mạnh:

Các yếu tố của mảng được sắp xếp theo các giá trị nhị phân của hằng liệt kê (có nghĩa là, bởi họ unsigned magnitude).

Đào vào mã CLR (2.0 SSCLI) và xuống cấp thấp hơn mức tôi thực sự cảm thấy thoải mái, có vẻ như cuối cùng là vì các giá trị enum nội bộ được lưu trữ trong một cái gì đó trông như thế này đây là C++):

class EnumEEClass : public EEClass 
{ 
    friend class EEClass; 

private: 

    DWORD   m_countPlusOne; // biased by 1 so zero can be used as uninit flag 
    union 
    { 
     void  *m_values; 
     BYTE  *m_byteValues; 
     USHORT  *m_shortValues; 
     UINT  *m_intValues; 
     UINT64  *m_longValues; 
    }; 
    LPCUTF8   *m_names; 

Như có thể thấy, đó là unsigned loại mà giữ giá trị thực tế - vì vậy khi những giá trị này được phát ra đếm, tự nhiên họ đang có trong unsigned thứ tự của chúng.

+8

Điều thú vị là, điều này bắt đầu như một lỗi (http://connect.microsoft.com/VisualStudio/feedback/details/98147/enum-getvalues). Nếu bạn nhìn vào các phiên bản trước của tài liệu trước 3.5 thì không có đề cập chính thức nào về việc nó sử dụng độ lớn chưa ký của mình. Do không có khả năng sửa chữa nó mà không phá vỡ các ứng dụng hiện có, tôi đoán họ chỉ cập nhật các tài liệu: D – keyboardP

+1

Cảm ơn @keyboardP, đó là những gì tôi đã thực sự yêu cầu. – gmletzkojr

+1

Câu trả lời hay. Tuy nhiên, nó giả định rằng người đọc biết các số âm được biểu diễn như thế nào (thực tế là [hai bổ sung] (http://en.wikipedia.org/wiki/Signed_number_representation), mặc dù [C# spec] (http: //www.ecma- international.org/publications/standards/Ecma-334.htm) không yêu cầu rõ ràng phương pháp này để đại diện cho các số nguyên đã ký).Kiến thức này là cần thiết để hiểu lý do tại sao đối xử với họ như là unsigned làm cho họ làm theo sau số tích cực. – stakx