2014-01-28 97 views
2

我可以確定delphi將遞增序列中的整數賦值給任何枚舉my create?將整數值轉換爲枚舉類型

type 
    TMyType = (mtFirst, mtSecond, mtThird); 

那裏肯定mtFirts總是TmyType(1) ???

我嘗試寫這樣myTypeselection := TMyType(MyRadiogroup.ItemIndex+1);

代碼,但我失敗了值整數數字在某種程度上混合。

+0

no,ist TMyType =(mtFirst,mtSecond,mtThird);總是等於TMyType =(mtFirst = 1,mtSecond = 2,mtThird = 3); – Franz

回答

6

documentation了答案:

默認情況下,枚舉值的序數從0開始,並按照其自己的標識符在類型聲明中列出的順序。

所以你認爲編號從一開始就是錯誤的。 ord(mtFirst)=0,ord(mtSecond)=1等就是這種情況。

這意味着你的代碼應閱讀:

myTypeselection := TMyType(MyRadiogroup.ItemIndex); 

由於單選按鈕組索引也是從零開始的。

在我自己的代碼,我用下面的泛型類像這樣進行操作:

type 
    TEnumeration<T> = class 
    strict private 
    class function TypeInfo: PTypeInfo; inline; static; 
    class function TypeData: PTypeData; inline; static; 
    public 
    class function IsEnumeration: Boolean; static; 
    class function ToOrdinal(Enum: T): Integer; inline; static; 
    class function FromOrdinal(Value: Integer): T; inline; static; 
    class function MinValue: Integer; inline; static; 
    class function MaxValue: Integer; inline; static; 
    class function InRange(Value: Integer): Boolean; inline; static; 
    class function EnsureRange(Value: Integer): Integer; inline; static; 
    end; 

class function TEnumeration<T>.TypeInfo: PTypeInfo; 
begin 
    Result := System.TypeInfo(T); 
end; 

class function TEnumeration<T>.TypeData: PTypeData; 
begin 
    Result := TypInfo.GetTypeData(TypeInfo); 
end; 

class function TEnumeration<T>.IsEnumeration: Boolean; 
begin 
    Result := TypeInfo.Kind=tkEnumeration; 
end; 

class function TEnumeration<T>.ToOrdinal(Enum: T): Integer; 
begin 
    Assert(IsEnumeration); 
    Assert(SizeOf(Enum)<=SizeOf(Result)); 
    Result := 0; 
    Move(Enum, Result, SizeOf(Enum)); 
    Assert(InRange(Result)); 
end; 

class function TEnumeration<T>.FromOrdinal(Value: Integer): T; 
begin 
    Assert(IsEnumeration); 
    Assert(InRange(Value)); 
    Assert(SizeOf(Result)<=SizeOf(Value)); 
    Move(Value, Result, SizeOf(Result)); 
end; 

class function TEnumeration<T>.MinValue: Integer; 
begin 
    Assert(IsEnumeration); 
    Result := TypeData.MinValue; 
end; 

class function TEnumeration<T>.MaxValue: Integer; 
begin 
    Assert(IsEnumeration); 
    Result := TypeData.MaxValue; 
end; 

class function TEnumeration<T>.InRange(Value: Integer): Boolean; 
var 
    ptd: PTypeData; 
begin 
    Assert(IsEnumeration); 
    ptd := TypeData; 
    Result := Math.InRange(Value, ptd.MinValue, ptd.MaxValue); 
end; 

class function TEnumeration<T>.EnsureRange(Value: Integer): Integer; 
var 
    ptd: PTypeData; 
begin 
    Assert(IsEnumeration); 
    ptd := TypeData; 
    Result := Math.EnsureRange(Value, ptd.MinValue, ptd.MaxValue); 
end; 

與在手你的代碼變成:

myTypeselection := TEnumeration<TMyType>.FromOrdinal(MyRadiogroup.ItemIndex); 
6

如果不指定值對於你的枚舉值,編譯器將從零開始,所以這個

TMyType = (mtFirst, mtSecond, mtThird) 

是等價的t到

TMyType = (mtFirst = 0, mtSecond = 1, mtThird = 2) 

如果使用正確的起始值0,則從整數投射到枚舉並返回是安全的。

+1

準確地說,你的兩個聲明不是等價的。編譯器不會爲第二個生成RTTI。 –