あなたの状態:
結果が定義されていない場合、これは私はいつも後から例外の場合の結果を定義することによって、すべての機能を開始しなければならないことを意味します。
関数が例外を発生させた場合、関数の戻り値が未定義であることが懸念されます。しかし、それは問題ではありません。機能fn
の体はコールバックサイトで、x
を割り当てるべきではありませんし、例外が発生した場合
x := fn();
:次のコードを考えてみましょう。論理上記ワンライナーは、2つのライナーとして考えることができる。
- コール
fn()
- 割り当て戻り値
x
に例外が1行目に上昇している場合、行2決してx
は決して割り当てられません。
Result
に割り当てる前に例外が発生した場合、関数が例外を発生させた場合、関数の戻り値を決して使用しないでください。
実際に気になるべきことは、関連する問題です。 Result
とに割り当てた場合、例外が発生するとどうなりますか? Result
に割り当てた値を関数外に伝播することは可能ですか?悲しいことに、答えは「はい」です。
Result
に割り当てた値は、多くの結果タイプ(たとえば、整数、ブール値など)に対して、その関数が例外を発生させた場合、関数の外部に伝播しません。ここまでは順調ですね。
しかし、いくつかの結果の型(文字列、動的配列、インタフェース参照、バリアントなど)には、問題を複雑にする実装の詳細があります。戻り値は、var
パラメータとして関数に渡されます。そして、関数の外から戻り値を初期化できることが分かりました。このように:fn
の本体が実行を開始すると
s := 'my string';
s := fn();
、Result
は値'my string'
を持っています。
procedure fn(var Result: string);
そして、これはあなたがResult
変数に割り当てると、あなたの関数が、その後例外が発生した場合でも、コール・サイトでの変更を見ることができることを意味しますfn
は次のように宣言されているかのようです。それを回避するためのきれいな方法はありません。あなたができることは、関数のローカル変数に代入して、関数の最終行為としてのみResultを代入することです。
function fn: string;
var
s: string;
begin
s := ...
... blah blah, maybe raise exception
Result := s;
end;
return
文が強く、ここで感じられるCスタイルの欠如。
上記の問題の影響を受けやすい結果変数の種類を正確に記述することは驚きです。当初は、問題がマネージタイプに影響したと思っていました。しかし、Arnaud氏は、レコードやオブジェクトも影響を受けるというコメントを述べている。レコードまたはオブジェクトがスタックに割り当てられている場合は、そうです。グローバル変数またはヒープ(例えばクラスのメンバー)が割り当てられている場合、コンパイラはこれを別々に扱います。ヒープ割り当てレコードの場合、暗黙のスタック割り当て変数が関数結果を返すために使用されます。関数が戻るときだけ、これはヒープ割り当て変数にコピーされます。コールサイトで関数結果変数を割り当てる値は、関数自体のセマンティクスに影響します。私の意見で
これはout
意味を持つとは対照的に、関数の戻り値はvar
意味を持っているため、それは、言語設計で、恐ろしい間違いだった理由のすべての非常に明確な説明図です。
例外が発生したときに「結果」にどのような価値があるかは重要ですか? –
+1からミカエル。私もこの問題を見ることができません。 –
可能な重複:デルファイの結果のデフォルト値(http://stackoverflow.com/q/5336863/576719)。 –