2016-07-14 10 views
2

を返すためのエレガントな方法は何ですか:少なくとも場合私はメソッドを持っているすべてのメソッドを実行し、組み合わせてブール結果

function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
begin 
    DoSomething('one'); 
    DoSomething('two'); 
    DoSomething('three'); 
end; 

function SomeClass.DoSomething(param: String): Boolean; 

は、この方法は、1つの方法で、例えば、頻繁に使用されているとしましょう1つのDoSomethingメソッドはFalseを返します。メソッド全体の結果はFalseでなければなりませんが、すべてのメソッド呼び出しで作業を行う必要があります。ただ醜いです

function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
var 
    r1, r2, r3: Boolean; 
begin 
    r1 := DoSomething('one'); 
    r2 := DoSomething('two'); 
    r3 := DoSomething('three'); 
    Result := r1 and r2 and r3; 
end; 

は今、私はこれを持っています。 DoSomething呼び出しをインライン化できません。最初のメソッドが返された場合は、 Falseの残りのメソッドはどれも最適化のために呼び出されません。私は思いつくことができないシンプルでエレガントな方法を欠いていると思う。

+1

既存のソリューションは問題ありませんが、変更しないでください理由を説明するコメントを追加します。しかし、副作用のある機能は危険です。おそらく、あなたはより基本的なレベルでデザインを再考する必要があります。あなたがこれを全く必要としているという事実は、より深刻な問題を示しています。 –

+0

はい、そうです。これは私が今保守している古いコードのいくつかの問題を示す例に過ぎません。残念ながら再設計はコストがかかりませんので、そのままゲームをしなければなりません。 – Vix

+0

だから、それを書いてコメントをつけて移動してください。レガシーコードの優雅さに心配しているのは不思議です。あなたが実際にエレガンスを課すためにそれを変更することができない場合は、あなたの懸念は何ですか? –

答えて

2

IMHO、より安全かつ簡単なパターンは、次のことがあります

function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
begin 
    result := DoSomething('one'); 
    if not DoSomething('two') then 
    result := false; 
    if not DoSomething('three') then 
    result := false; 
end; 

読んで理解することは明らかです。

その他のメソッドは、現在のブール式の評価設定に基づいているため、エラーが発生しやすくなります。

booleanの代わりに列挙型を返すことも考えてください。これにより、コードロジックがより明示的になる可能性があります。falseはエラーですか?より良い返信dsFailedTDoSomeThingResult = (dsSuccess, dsFailed)です。

+0

@ michael-vincentの代わりにこれを使うつもりです(これもとても良いです)。 +これは、どのバージョンのDelphiでも動作するということです。 – Vix

+0

これは質問のコードよりはるかに醜いです! –

+0

なぜですか?その普遍的で、直接的で、安全で、余分な変数は必要ありません。すべての議論に対して? – Vix

2

リスト内の異なるパラメータを渡すのはどうですか?ような何か:

function DoSomethingManyTimes(const AList: array of String); 
var 
    ss: string; 
begin 
    result := true; 
    for ss in AList do begin 
    result := DoSomething(ss) and result; 
    end; 
end; 
+0

前回の呼び出しで 'result'が' False'に設定されたときに 'DoSomething'を呼び出すように、' result:= resultとDoSomething(ss); – Vix

+1

@Vixと 'result:= DoSomething(ss)and result;' (ヨーダスタイル) –

+0

@Vixとまったく同じように動作するはずですが、結果をローカル変数に保存して、結果と...で使用することができます。 –

2

あなたはコードの前complete Boolean expression evaluation *を有効にしてから、後でそれを無効にすることができます

BOOLEVALディレクティブ ON
function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
begin 
    {$IFOPT B-} 
    {$DEFINE BOOLEVALISOFF} 
    {$BOOLEVAL ON} 
    {$ENDIF} 

    Result := DoSomething('one') and 
      DoSomething('two') and 
      DoSomething('three'); 

    {$IFDEF BOOLEVALISOFF} 
    {$UNDEF BOOLEVALISOFF} 
    {$BOOLEVAL OFF} 
    {$ENDIF} 
end; 

、コンパイラも、各式の結果を評価し、コードを生成します。全体的な結果はすでにわかっていますが、すべての関数が呼び出されます。

(*この指示文は、マニュアルではBoolean short-circuit evaluationと呼ばれていますが、逆の動作をするので混乱します)。

+1

コードユニットがすでに 'BOOLEVAL ON'にある場合、これは既存のコードを破るでしょう...だから私はこの方向には進まないでしょう。 –

+2

@Arnaud: '{$ IFOPT B - } {$ DEFINE BOOLEVALISOFF} {$ ELSE} {$ UNDEF BOOLEVALISOFF} {$ ENDIF}'などを使って元の状態に戻すことができます。 –

+1

質問にあるように、完全にはっきりとしたコードを避けるために必要なこと。単純にする! –

-3

これを達成する方法は複数あります。

(私の意見に基づいて)最も簡単かつ明確な方法は、あなたが特定のパラメータの結果が真であることを必要とするときにも同様のアプローチを使用することができますので、

function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
begin 
    if DoSomething('one') and 
    DoSomething('two') and 
    DoSomething('three') = true then Result := True 
    else Result := False; 
end; 

のような複数の条件でif文を使用することですが、他のためにそのような偽です:

function SomeClass.DoSomethingManyTimesForDifferentParams: Boolean; 
begin 
    if (DoSomething('one') = True) and 
    (DoSomething('two') = True) and 
    (DoSomething('three') = False) = True then Result := True 
    else Result := False; 
end; 

この例では、全体的な機能は、DoSomethingへの最初の2つのコールがTrueを返しますし、何かをする最後の呼び出しが希望する場合にのみTrueを発生します返信False。 前の例では必要ではないが、必要に応じて各別の条件をそれ自身のかっこに入れることに注意してください。

あなたには、いくつかのリストでは、あなたのパラメータを持っている場合は、ループの中から、あなたのDoSomethingメソッドを呼び出すなどの結果を確認し、あなたが多数、あるいはダイナミックを持っている場合は、ループを使用して、最後のアプローチは特に便利来るので

function DoSomethingManyTimes(const AList: array of String): Boolean; 
var 
    ss: string; 
begin 
    for ss in AList do begin 
    result := DoSomething(ss); 
    //Break the loop if the result previously called DoSomething is False 
    //to avoid calling DoSomething for every input parameter. 
    if Result = False then Break; 
    end; 
end; 

DoSomethingメソッドに送信するパラメータの数。しかし、それはDoSomethingがすべてのパラメータに対してtrueを返すことを期待しているので、2番目の例のように異なる組み合わせの能力がないので、制限があります。TrueFalse結果

+0

ブール値を返す関数で "= True"を使用することは時代遅れです。短絡ブール評価(デフォルト)では、式の残りの部分が結果を変更しないとすぐに評価が中止されるため、すべての関数が呼び出されるという保証はありません。元の質問で使用された方法は、これを行うための最も簡単で読みやすい方法です。 –

+0

Booleana = trueの場合、result:= true else result:= falseはresult:= booleanaと等価であるため意味がありません。 –

+2

再び、短絡評価という点を逃した答え。 -1 –

関連する問題