2012-01-29 78 views
11

考慮以下過程操作者的正確「在」操作符的使用

procedure InTests; 
var 
    N, K: Integer; 

begin 
    N:= 1111; 
    if N in [6, 8, 10]   // this is correct, readable and effective code 
    then ShowMessage('OK'); 

    K:= 11; 
    if N in [6, 8, 10, K]  // this is correct but less effective 
    then ShowMessage('OK'); // (compiler creates local 16-bytes set var) 

    K:= 1111; 
    if N in [6, 8, 10, K]  // this is a bug (K > 255) 
    then ShowMessage('OK'); 
end; 

in代替if

if (N = 6) or (N = 8) or (N = 10) 
    then ShowMessage('OK'); 

使得代碼更加緊湊和可讀,但Delphi的文檔是沉默它,並你應該意識到潛在的問題。

的問題是:應該在in運營商使用,只有在括號中的常量,例如

if N in [6, 8, 10] 
    then ShowMessage('OK'); 

被認爲是在Delphi中的好做法?

+4

是的,但你顯示的是文字,而不是常數。也就是說,我會將'MEANINGFULNAME = 6;'在const部分中的某個地方聲明並在'in'條件中使用它。使用文字是我不認爲是一種好的做法(很難搜索,而且當你需要改變一個值時你很可能會錯過)。 – 2012-01-29 09:48:53

+0

@MarjanVenema你是一個真正的純粹程序員:) – kludg 2012-01-29 09:58:33

+0

我會把它當作讚美:)不知道純粹主義者,只是通過使用文字代碼刺激了很多次...... – 2012-01-29 10:00:56

回答

1

你在這裏有一個set of byte。你應該問自己的問題是set of byte是否真的是你的數字代表的?你有「幻數」在這裏,雖然我明白,這只是一個樣本,你必須考慮的是,雖然

if Token in [TokenString, TokenNumber, TokenChar] then 

...會被認爲是很好的做法,這樣的:

if N in [2, 12, 14, 19] then 

。 ..不會。

然而,在第一種情況下(稱爲令牌),明確集合類型將更加好的做法:

type TokenSet = (TokenNone, TokenString, TokenChar,...) 

然後第一個樣品是明確一個很好的做法。

+0

這個問題不是關於魔術數字。我可以編輯它來刪除幻數。 – kludg 2012-01-29 10:01:51

+0

不應該讀「const TokenSet =」而不是「type TokenSet =」? – 2012-01-29 10:14:29

+0

@Uwe,不,它是一個集合類型(http://delphi.about.com/od/beginners/a/delphi_set_type。htm) – 2012-01-29 10:16:54

4

這是絕對好的做法。它使代碼更具可讀性,消除了對邏輯運算符,括號等的需求。我會一直使用in進行這樣的測試。

唯一的缺點是德爾福對sets的支持非常有限(基本序數類型不能超過256個值)。但是,如果你不受這些限制,那麼你應該毫不猶豫地使用in