適当な実装をした場合、戻り値は不定になるのか? というか不定って何?
というような適当実験。
今回長い。
その1
function TForm1.Hoge: string;
begin
end;
実装
無名メソッドではなく、普通のメソッド。
実装は空っぽ。
結果
空文字。
その2
function TForm1.Hoge: string;
begin
Result := (function : string
begin
end)();
if not Result.IsEmpty then Exit('123');
Result := (function : string
begin
Result := 'abc';
end)();
end;
実装
「実装が空っぽ」の無名メソッドを呼び出し、
その時の戻り値が空かどうか調べ、(空でないならExit)
最後まで到達したら無名メソッドで「abc」を返します。
結果
abc
考察
「実装が空っぽ」の無名メソッドであっても、変な値を返すわけではないようです。
その3
function TForm1.Hoge: string;
var
i : Integer;
begin
for i := 0 to 1 do
begin
Result := (function : string
begin
end)();
if not Result.IsEmpty then Exit('123');
Result := (function : string
begin
Result := 'abc';
end)();
end;
end;
実装
「実装が空っぽ」の無名メソッドを呼び出し、
その時の戻り値が空かどうか調べ、(空でないならExit)
最後まで到達したら無名メソッドで「abc」を返します。
上記をループで2回実行します。
結果
123
考察
デバッグすると分かりますが、一回目のループでのResultは
・Result := 空
・Result := abc
であり、
二回目のループで
・Result := abc のまま!
・Exit句で123 で抜ける
という動作をします。
一個目の無名メソッドが「何もしない何か」あるいは「abcを返す」ようです。
その4
function TForm1.Hoge: string;
var
i : Integer;
begin
for i := 0 to 1 do
begin
Result := (function : string
begin
Result := '';
end)();
if not Result.IsEmpty then Exit('123');
Result := (function : string
begin
Result := 'abc';
end)();
end;
end;
実装
「空文字を返す」の無名メソッドを呼び出し、
その時の戻り値が空かどうか調べ、(空でないならExit)
最後まで到達したら無名メソッドで「abc」を返します。
上記をループで2回実行します。
結果
abc
考察
一個目の無名メソッドで「Result := '';」を明示すれば、きちんと空文字を返すようになり、本体メソッド結果はabcになります。
その5
function TForm1.Hoge: string;
var
i : Integer;
begin
for i := 0 to 1 do
begin
if i = 1 then
begin
Result := (function : string
begin
end)()
+
(function : string
begin
end)();
Exit;
end;
Result := (function : string
begin
Result := 'abc';
end)();
end;
end;
実装
1回目のループではResult にabcを入れて、
2回目のループで実装が空っぽの無名メソッドの戻り値をくっつけてExit。
結果
空
考察
ループさせた時の「実装が空っぽ」の無名メソッドは、先ほどみた限りでは「何もしない何か」or「abcを返す」でしたが、今回は「空」が返ってきます。
その6
function TForm1.Hoge: string;
type
TAct = reference to function : string;
var
act : TAct;
begin
act := (function : string
begin
end);
Result := (function : string
begin
Result := 'abc';
end)();
end;
実装
無名メソッドの代入先を宣言してみます。
宣言だけして、使用しません。
結果
abc
考察
まあ当たり前ですね。
その7
function TForm1.Hoge: string;
type
TAct = reference to function : string;
var
act : TAct;
begin
act := (function : string
begin
end);
Result := (function : string
begin
Result := 'abc';
end)();
Result := act;
end;
実装
無名メソッドの代入先を宣言してみます。
一度別の値を無名メソッドで入れて、
最後に空っぽのメソッドを呼び出します。
結果
abc
考察
またしても「何もしない何か」or「abcを返す」となりました。
その8
function TForm1.Hoge: string;
type
TAct = reference to function(n :Integer) : string;
var
act : TAct;
i : Integer;
begin
act := (function(n :Integer):string
begin
if n = 0 then Exit('あいうえお');
if n = 1 then Exit;
end);
for i := 0 to 1 do
begin
Result := act(i);
end;
end;
実装
引数に応じて戻り値を返す無名メソッドです。
n = 0 の時は「あいうえお」
n = 1 の時は特に戻り値を指定しません。
この無名メソッドをループで2回呼び出します。
結果
あいうえお
考察
2回目の結果が「何もしない何か」or「あいうえおを返す」となりました。
その9
function TForm1.Fuga(n: Integer): string;
begin
if n = 0 then Exit('あいうえお');
if n = 1 then Exit;
end;
function TForm1.Hoge: string;
var
i : Integer;
begin
for i := 0 to 1 do
begin
Result := Fuga(i);
end;
end;
実装
無名メソッドを止めてみた
結果
あいうえお
考察
2回目の結果が「何もしない何か」or「あいうえおを返す」となりました。
その10
function TForm1.Fuga(n: Integer): string;
begin
if n = 0 then Exit('あいうえお');
if n = 1 then Exit;
end;
function TForm1.FugaFuga(n: Integer): string;
begin
if n = 0 then Exit('かきくけこ');
if n = 1 then Exit;
end;
function TForm1.Hoge: string;
begin
Result := Fuga(0);
Result := FugaFuga(1);
end;
実装
似ている二つのメソッドを実装、呼び出してみた。
引数0の時は戻り値を指定して返す。
引数1の時は戻り値を指定しない。
結果
あいうえお
考察
2回目の結果が「何もしない何か」or「別メソッドの結果を返す」となりました。
というわけで
なんとなくわかると思いますが、
・メソッドの戻り値にはデフォルト値がある(今回はstringなので空文字)
・戻り値を明示しない場合、「何もしない」
・戻り値を明示せず、かつメソッドの戻り値を直参照するとデフォルト値を返す
のような動きをします。
「不定」というのは変な値になることではなく、戻り値として参照できる値を返す、といった結果になるようです。
Resultに格納されているアドレスや関数の呼び出し順序なんかに依存してるんでしょう。たぶん。
(ここにきて超絶適当)
Result を初期化するクセをつけておけばいいというだけの話でした。