質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

意見交換

クローズ

1回答

548閲覧

C#:delegate関数実行時の挙動について

peeping_tom

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework 4.0

Microsoft Windows用のソフトウェア開発環境/実行環境である .NET Frameworkの4番目のメジャーバージョンです。

Visual Studio 2013

Microsoft Visual Studio 2013は、Microsoftによる統合開発環境(IDE)であり、多種多様なプログラミング言語に対応しています。 Visual Studio 2012の次のバージョンです

0グッド

0クリップ

投稿2023/08/23 13:52

編集2023/08/23 14:21

0

0

目的

 delegate関数実行時の挙動に対して、納得のいく解釈が自分の中で出来ておらず、以下のdelegate関数実行に於ける挙動の考察が尤もか、異なる考えが有るか伺いたいです。

背景となる問題点

 パラメータを要する関数に対して、事前にパラメータを渡しdelegate化、そして配列変数的に運用する事を想定しています。
そして然る後、for文等で順次実行する事を想定していますが、その際にdelegate化の折り関数に渡したパラメータとする配列の要素に於いてIndexOutOfRangeExceptionのエラーが生じます。

挙動に対する考察:

  • delegate関数は実行の際に、其の関数の定義を参照する。
  • 其の際に、関数にパラメータが渡される場合、其れが配列の要素であるならば、其の要素番号諸共遡って参照する。つまり配列要素とするメモリ上の実態とする値の番地を参照しない ➡ 此の時今回のコードならば、要素番号は最新のもの=配列外である為、上記エラーを生じた。
  • ならば、delegateの挙動はdelegateの内部関数とパラメータを参照する場合、メモリを具体的に参照するよりは、逐次コードを解釈しているように感じている   ➡此の行の抽象的な解釈は、専門外で妥当か不明

VC#

1class test 2 { 3 delegeter[] funcs; 4 string[] testparams = new string[] { "0", "1", "2", "3" }; 5 6 public delegate void delegeter(); 7 8 public void realdelegeter(string testparam) 9 { 10 Console.WriteLine(testparam); 11 } 12 13 public test() 14 { 15 funcs = new delegeter[testparams.Length]; 16 17 for (int i = 0; i < funcs.Length; i++) 18 { 19 string tst = testparams[i]; 20///invoke()から下記を参照した際に、何故かi が funcs.Lengthに成ってエラーになる⇒そういう仕様か?私にも分からん 21 funcs[i] = () => realdelegeter(testparams[i]); 22///上記から此の様に変更する解決する。恐らく定義時のパラメータを参照?か共通の値を得ている。でも釈然とせん 23 funcs[i] = () => realdelegeter(tst); 24 } 25 } 26 public void invoke() 27 { 28 for (int i = 0; i < funcs.Length; i++) funcs[i](); 29 } 30 }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

回答1

#1

naitou

総合スコア141

投稿2023/08/23 15:21

編集2023/08/23 15:25

ラムダ式の変数キャプチャに関わる内容と思われます。ラムダ式の変数キャプチャについては以下をご参考下さい。
https://learn.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/lambda-expressions#capture-of-outer-variables-and-variable-scope-in-lambda-expressions

何故かi が funcs.Lengthに成ってエラーになる

i は for文のループ終了時のfuncs.Lengthになっているからです。
ラムダ式の変数キャプチャにより、該当デリゲートがガベージ コレクションされるまで for文内の i はガベージコレクションされずに存在し続けています。

string tst = testparams[i];

とすると、forループ毎に宣言した tst が 該当デリゲート毎に存在している状態です。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

最新の回答から1ヶ月経過したため この意見交換はクローズされました

意見をやりとりしたい話題がある場合は質問してみましょう!

質問する

関連した質問