2009-09-14 36 views
16

Tôi đã khai báo loại enum sau đây, trong đó tôi muốn thành viên đầu tiên có giá trị thứ tự là 1 (một) thay vì 0 thông thường (0) :Tại sao tôi nhận được lỗi "loại không có typeinfo" với kiểu enum

type 
    TMyEnum = (
       meFirstValue = 1, 
       meSecondValue, 
       meThirdValue 
      ); 

Nếu tôi gọi TypeInfo(), ví dụ: như một phần của một cuộc gọi đến GetEnumName(), tôi nhận được một lỗi biên dịch:

GetEnumName(TypeInfo(TMyEnum), Ord(aValue)); 

LỖI: "E2134: Loại 'TMyEnum' không có typeinfo"

Tại sao điều này?

Tôi biết rằng các lớp học chỉ có typeinfo nếu họ được biên soạn với $ M tùy chọn trình biên dịch được kích hoạt hay (có nguồn gốc từ một số lớp đó là, chẳng hạn như TPersistent) nhưng tôi không nghĩ có bất kỳ điều kiện đặc biệt để có typeinfo cho các loại enum.

Trả lời

18

Thông tin loại không được hỗ trợ cho enums trong đó các giá trị thứ tự cụ thể được gán cho kết quả trong các thành viên enum có giá trị thứ tự khác với giá trị bình thường được trình biên dịch gán.

Nếu giá trị cụ thể là cần thiết hoặc mong muốn, "không sử dụng" thành viên enum sẽ phải được chèn vào "pad" enum theo yêu cầu. ví dụ (bổ sung thụt đầu dòng cho chỉ nhấn mạnh):

type 
    TMyEnum = (
       meNOTUSED1, {= 0} 
       meFirstValue, {= 1} 
       meSecondValue, 
       meThirdValue 
      ); 

Một subrange sau đó có thể được sử dụng để "lọc" ra những giá trị ban đầu không sử dụng:

TValidMyEnum = meFirstValue..meThirdValue; 

Mặc dù sau đó bạn có thể muốn xem xét đổi tên enum gốc gõ để loại sắp xếp của bạn có thể được sử dụng trong suốt dự án của bạn.

Một subrange là chưa đủ nếu enum chứa "khoảng trống":

type 
    TMyEnum = (
       meNOTUSED1, {= 0} 
       meFirstValue, {= 1} 
       meSecondValue, 
       meThirdValue, 
       meNOTUSED2, 
       meFinalValue {= 5} 
      ); 

Trong trường hợp này không có đơn giản là cách để mở rộng phạm vi thời gian biên dịch kiểm tra để loại trừ các thành viên không sử dụng, nhưng một vài thiết lập các loại sẽ đơn giản hóa công việc kinh doanh thực hiện bất kỳ cần thiết runtime kiểm tra:

type 
    TMyEnums = set of TMyEnum; 

    const 
    meNOTUSED  = [meUNUSED1, meUNUSED2]; // .. etc as required 
    meValidValues = [Low(TMyEnum)..High(TMyEnum)] - meNOTUSED; 


    if NOT (aValue in meValidValues) then 
    // etc 
+2

lẽ bạn có thể làm giảm bớt sự đau đớn để làm điều này bằng cách sử dụng một loại subrange: loại TMyEnumWithDummy = ( meNOTUSED, meFirstValue, meSecondValue, meThirdValue ); TMyEnum = Succ (meNOTUSED) ..Cao (TMyEnumWithDummy); –

+1

Có thực sự, mặc dù nếu bạn có "khoảng trống" trong enum sau đó một subrange đơn giản sẽ không đủ. Trong trường hợp tôi bắt gặp vấn đề này, tôi đã có những khoảng trống - Thật không may, tôi đã đơn giản hóa quá mức cho "câu hỏi" ban đầu. Nhưng tôi cũng sẽ cập nhật câu trả lời với đề xuất của bạn. – Deltics

28

enumerations kề nhau và kiểu liệt kê mà không bắt đầu từ zero không có typeinfo. Để typeinfo được triển khai, nó sẽ cần phải ở định dạng khác với tkEnumeration hiện tại, do các vấn đề tương thích ngược.

Tôi xem xét việc triển khai một tkDiscontiguousEnumeration (hoặc có thể là thành viên có tên tốt hơn) cho Delphi 2010, nhưng lợi ích dường như nhỏ xem xét sự khan hiếm tương đối của họ và những khó khăn trong liệt kê - làm thế nào để bạn mã hóa các dãy hiệu quả? Một số mã hóa tốt hơn cho một số tình huống, tệ hơn cho người khác.

+6

Đó là một số thông tin cơ bản hữu ích và thú vị. Bạn có thể ít nhất đã xem xét việc cập nhật tài liệu cho lỗi E2134. Điều này cung cấp một ví dụ về nơi typeinfo không được tạo ra nhưng không đưa ra bất kỳ manh mối nào cho những cân nhắc này đối với các loại enum. Sau đó, một lần nữa, nó được thực hiện gần 15 năm rắn Delphi'ing cho tôi vấp ngã này, vì vậy khi bạn nói nó không chính xác là một vấn đề phổ biến. :) – Deltics

Các vấn đề liên quan