2011-04-04 28 views
4

是否可以編寫一個方法將任何序號類型作爲參數? Inc()或High()做同樣的方法嗎?傳遞一個序號參數

我使用的是2007年德爾福

+2

你想做什麼?不是簡單的重載方法的解決方案? – 2011-04-04 15:41:57

+0

重載的方法我需要爲每個我想使用的枚舉編寫一個新的方法。 – 2011-04-04 15:47:55

+1

@JamesB,那麼?你的問題是否可以編寫一個採用任何序數的函數。重載是一種有效的方式。 David的答案是最接近Inc()或High()的。你沒有在你的問題中的任何地方說過你的函數會做什麼,或者在參數中會收到什麼樣的序數。即使枚舉是「技術上」序數,它們也會被更恰當地描述爲「數組」(概念和實現)。此外,枚舉的大小是可變的(8到256位),這使得編寫泛型方法變得更加困難。 – 2011-04-05 07:02:47

回答

6

你需要使用一個untyped parameter

procedure Foo(const ordinal); 

procedure Foo(var ordinal); 

當然,你在某種程度上,你可以做什麼限制在這樣的例程裏面,因爲你已經放棄了類型系統。

+0

序號的大小是否保證爲4字節? – 2011-04-04 15:38:02

+0

不,它不是... – 2011-04-04 15:38:41

+3

那麼,現在你可以將*任何*傳遞給這些程序,而不僅僅是序號。所以這不是'inc'等工作原理。 (的確,代碼洞察力認爲'inc'的參數是'var X:ordinal',但是這種行爲你不能在你自己的proc/func中獲得,我想。) – 2011-04-04 15:38:54

1

找到了一種可能的方式,可能不是你所期望的,但嘿,我找到了一種方法!使用Variants。將無類型參數傳遞給一個過程的問題是你得到一個普通的指針,沒有類型信息,所以你不能對它做任何有用的事情。字節是1個字節,多達256個元素的枚舉是1個字節字節,最多2^16個元素的枚舉是2個字節,整數是4個字節(除非它們是8)。但有一種類型允許傳遞任何東西,並關心足夠的類型信息以使事情發揮作用:Variant。我故意在Delphi 7中寫了下面的例子,以確保我不會意外地使用任何Delphi 2010或Delphi XE的善良。

編輯:更新了代碼示例來處理一個被認爲序號由Variants.VarTypeIsOrdinal任何類型。包括所有整數類型+布爾值。顯然Enum被視爲Byte,所以它也吞下了。

program Project1; 

{$APPTYPE CONSOLE} 

uses 
    ExceptionLog, 
    SysUtils, Variants; 

type TSomeEnum = (e0, e1, e2, e3, e4); 

procedure DoSomethingWithEnum(V: Variant); 
var i: Integer; 
    b: Byte; 
    lw: LongWord; // Cardinal! 
    i64: Integer; 
begin 
    case VarType(V) of 
    varInt64: 
     begin 
     i64 := V; 
     WriteLn(i64); 
     end; 
    varSmallint, varInteger, varShortInt: 
     begin 
     i := V; 
     WriteLn(i); 
     end; 
    varByte: 
     begin 
     b := V; 
     WriteLn(b); 
     end; 
    varWord, varLongWord: 
     begin 
     lw := V; 
     WriteLn(lw); 
     end; 
    varBoolean: 
     begin 
     if V then WriteLn('True') else WriteLn('False'); 
     end; 
    else WriteLn('NOT a variant type (type = #' + IntToStr(Ord(VarType(V)))); 
    end; 
end; 

var i: Integer; 
    b: Byte; 
    c: Cardinal; 
    enum: TSomeEnum; 
    w: Word; 
    si: Shortint; 

begin 
    i := 1; 
    b := 2; 
    c := 3; 
    enum := e4; 
    w := 5; 
    si := -6; 

    DoSomethingWithEnum(i); 
    DoSomethingWithEnum(b); 
    DoSomethingWithEnum(c); 
    DoSomethingWithEnum(enum); 
    DoSomethingWithEnum(True); 
    DoSomethingWithEnum(w); 
    DoSomethingWithEnum(si); 

    Readln; 
end. 
+1

運行時變體的性能還有很多不足之處。 – 2011-04-04 17:41:24

+2

@Warren,Variants可能不如我們希望的那麼快,但它們也不那麼慢。 – 2011-04-04 18:25:55

0

之所以這樣做是困難的是,公司(X),DEC(x)和其他類似強的鬆(x)和SUCC(x)的實際,由編譯器生成,並且,如果你就像函數式的語法糖超過固有的編譯器操作一樣。

你可以像一些人建議的那樣,通過重載來做一些這樣的事情,其中​​一些是巧妙地使用泛型,另一些則使用泛型。但是對於模擬這些功能來說沒有什麼方便,或者功能上完全一樣。

例如,對於所有有序類型(包括Enums,Integers和這些類型的子範圍),編譯器都實現了Inc()(經典「Wirth」Pascal的一個現在頗爲模糊的功能是,所有類型都可以在這些類型上定義子範圍類型)。

如果您實際上告訴了我們更多關於您正在做的事的信息,可能會更加接近。但是一般的答案是,不,甚至沒有Inc和Dec的源代碼,因爲這些是編譯器原語。如果有功能Inc的RTL源代碼,你可以看看它,並適應它。 (x)可以定義爲x:= Succ(x),但是,那麼如何定義Succ(x)?由於x:= Inc(x)?你看。在某個時候,編譯器「魔術師」接管了。