C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

引数のあるメソッドをメソッドに渡す /B.B (19/03/09(Sat) 11:13) #90412
Re[1]: 引数のあるメソッドをメソッドに渡す /魔界の仮面弁士 (19/03/09(Sat) 13:11) #90414
│└ Re[2]: 引数のあるメソッドをメソッドに渡す /B.B (19/03/09(Sat) 16:18) #90417 解決済み
│  └ Re[3]: 引数のあるメソッドをメソッドに渡す /魔界の仮面弁士 (19/03/09(Sat) 22:26) #90425 解決済み
│    └ Re[4]: 引数のあるメソッドをメソッドに渡す /B.B (19/03/10(Sun) 09:36) #90426
│      └ Re[5]: 引数のあるメソッドをメソッドに渡す /魔界の仮面弁士 (19/03/11(Mon) 10:40) #90430
│        └ Re[6]: 引数のあるメソッドをメソッドに渡す /B.B (19/03/11(Mon) 23:09) #90442
Re[1]: 引数のあるメソッドをメソッドに渡す /キングダム (19/03/09(Sat) 12:39) #90413
  └ Re[2]: 引数のあるメソッドをメソッドに渡す /B.B (19/03/09(Sat) 15:51) #90416


親記事 / ▼[ 90414 ] ▼[ 90413 ]
■90412 / 親階層)  引数のあるメソッドをメソッドに渡す
□投稿者/ B.B (11回)-(2019/03/09(Sat) 11:13:52)

分類:[C#] 

Visual Studio 2017

お世話になります

表題の件ですがネットの検索では以下のように実装できました。

private void button1_Click(object sender, EventArgs e)
{
    int result = hogeMethod(method1);
    MessageBox.Show(result.ToString());
}

delegate int SimpleFunc(int x);

private int hogeMethod(SimpleFunc func)
{
    int a = 10;
    return func(a);
}

private int method1(int i)
{
    i = i * 2;
    return i;
}

しかしデリゲードはなかったことにしろという文言をよく見かけます
#90396で教えていただいた
isSuccessful = hogeMethod(() => Method3("ほげほげ"));
のようなラムダ式での記述の仕方を教えて欲しいのです
よろしくお願いします

[ □ Tree ] 返信 編集キー/

▲[ 90412 ] / ▼[ 90417 ]
■90414 / 1階層)  Re[1]: 引数のあるメソッドをメソッドに渡す
□投稿者/ 魔界の仮面弁士 (2091回)-(2019/03/09(Sat) 13:11:11)
2019/03/09(Sat) 13:26:31 編集(投稿者)

No90412 (B.B さん) に返信
> delegate int SimpleFunc(int x);
> private int hogeMethod(SimpleFunc func)

.NET Framework 3.5 以降をお使いであれば、Func<> や Action<> が用意されているので、
  private int hogeMethod(Func<int, int> func)
で済ますこともできますね。


> しかしデリゲードはなかったことにしろという文言をよく見かけます
デリゲート(delegate)ですよ;
デリゲードでもデリケートでも無く。


> #90396で教えていただいた
> isSuccessful = hogeMethod(() => Method3("ほげほげ"));
> のようなラムダ式での記述の仕方を教えて欲しいのです

どの部分を書き換えたいのかが読み取れなかったのですが、
> private int method1(int i)
> {
>   i = i * 2;
>   return i;
> }
については、「式形式」のメソッドで書けます。


// 要 C# 6.0 以降
private int method1(int i) => i * 2;


hogeMethod(SimpleFunc func) の書き換えなら、
 private int hogeMethod(SimpleFunc func) => func(10);
 private int hogeMethod(SimpleFunc func) => (func ?? delegate { return -1; })(10);
 private int hogeMethod(SimpleFunc func) => func?.Invoke(10) ?? -1;
 private int hogeMethod(SimpleFunc func)=> func != null ? func(10) : throw new ArgumentNullException(nameof(func), "引数が空やで");
とか。


button1 での「int result = hogeMethod(method1);」のところで
method1 メソッドを定義せずに呼び出したいなら、

// 要 C# 2.0 以降
SimpleFunc proc = new SimpleFunc(delegate(int i) { i *= 2; return i; });
int result = hogeMethod(proc);

// 要 C# 2.0 以降
SimpleFunc proc = delegate(int i) { i *= 2; return i; };
int result = hogeMethod(proc);

// 要 C# 3.0 以降
SimpleFunc proc = (int i) => { i *= 2; return i; };
int result = hogeMethod(proc);

// 要 C# 3.0 以降
SimpleFunc proc = (i) => { i *= 2; return i; };
int result = hogeMethod(proc);

// 要 C# 3.0 以降
SimpleFunc proc = i => { i *= 2; return i; };
int result = hogeMethod(proc);



// 要 C# 2.0 以降
SimpleFunc proc = delegate(int i) { return i * 2; };
int result = hogeMethod(proc);

// 要 C# 2.0 以降
int result = hogeMethod(delegate (int i) { return i * 2; });

// 要 C# 3.0 以降
SimpleFunc proc = i => { return i * 2; };
int result = hogeMethod(proc);

// 要 C# 3.0 以降
int result = hogeMethod(i => { return i * 2; });

// 要 C# 3.0 以降
int result = hogeMethod(i => i * 2);
[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90414 ] / ▼[ 90425 ]
■90417 / 2階層)  Re[2]: 引数のあるメソッドをメソッドに渡す
□投稿者/ B.B (13回)-(2019/03/09(Sat) 16:18:41)
2019/03/09(Sat) 16:19:34 編集(投稿者)
No90414 (魔界の仮面弁士 さん) に返信
> .NET Framework 3.5 以降をお使いであれば、Func<> や Action<> が用意されているので、
>   private int hogeMethod(Func<int, int> func)
> で済ますこともできますね。

デリゲート(*/∇\*)

やりたいことが提示できてなかったようで申し訳ありあません

delegate int SimpleFunc(int x);
この記述を書きたくないということでした。

private int hogeMethod(Func<int, int> func)で解決しました、ありがとうございました。


private void button1_Click(object sender, EventArgs e)
{
    int result = hogeMethod(method1);
    MessageBox.Show(result.ToString());
}

private int hogeMethod(Func<int, int> func)
{
    int a = 10;
    return func(a);
}

private int method1(int i)
{
    i = i * 2;
    return i;
}

解決済み
[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90417 ] / ▼[ 90426 ]
■90425 / 3階層)  Re[3]: 引数のあるメソッドをメソッドに渡す
□投稿者/ 魔界の仮面弁士 (2094回)-(2019/03/09(Sat) 22:26:39)
No90412 (B.B さん) に返信
> しかしデリゲードはなかったことにしろという文言をよく見かけます

Delegate 型を無くしたらイベントすら扱えなくなりますよね。
delegate キーワードのことを言っているのでしょうか。

一応、解決済みマークはつけたままの状態にしておきますが、
前後の文脈が気になるので、具体的にどこに記載されていたのかを教えて欲しいです。


もしもそれが、
 SimpleFunc f1 = i => i * 2;
と書けるようになったので、C# 2.0 時代のような
 SimpleFunc f1 = delegate(int i) { return i * 2; };
の形式で記述する必要はもはや無くなった…という意味で
書かれているのだとしたら、それはその通りだと思います。

ただしラムダ式では、デリゲートと同じシグネチャが求められるので、
 button1.Click += (sender, e) => { label1.Text += "x"; };
を、たとえ引数が不要だったとしても、
 button1.Click += () => { label1.Text += "x"; }; // これは NG
のように書くことはできないという制限があるのに対し、
delegate キーワードであれば、
 button1.Click += delegate { label1.Text += "x"; };
のように、引数付きのデリゲートに引数無しの匿名関数を
割り当てることが可能という違いはあったりします。



> #90396で教えていただいた
> isSuccessful = hogeMethod(() => Method3("ほげほげ"));
> のようなラムダ式での記述の仕方を教えて欲しいのです

『() => Method3("ほげほげ")』の部分が「ラムダ式」ですね。



No90417 (B.B さん) に返信
> delegate int SimpleFunc(int x);
> この記述を書きたくないということでした。

えぇと…それはラムダ式とは関係ないです。(^_^:
Func<,> はジェネリックなデリゲート型ですね。


ラムダ式とは C# 3.0 で追加された構文で、先の例で言えば
複数行ラムダ構文の
  (int i) => { i = i * 2; return i * 2; }
や、あるいはより単純な単行ラムダ構文の
  i => i * 2;
などの表記を指します。


ラムダ式を受け取る変数の型は、Delegate もしくは Expression に限られます。

static void Main()
{
 // デリゲート型に対して、匿名メソッド式を代入
 Func<int, int> x = delegate (int i) { return i * 2; };

 // デリゲート型に対して、ラムダ式を代入
 Func<int, int> y = i => i * 2;

 // Expression 型に対して、ラムダ式を代入
 Expression<Func<int, int>> z = i => i * 2;

 // ローカル関数の宣言
 int f1(int i) { return i * 2; }

 // ローカル関数の宣言(式形式)
 int f2(int i) => i * 2; // これはラムダ式ではない
}



ラムダ式は、デリゲートに対して代入すると匿名メソッド式として扱われ、
Expression 型の変数に代入した場合は式木 (expression tree) となるため、
ラムダ式を代入する変数を
 var z = (int i) => i * 2;
のように型推論で宣言することはできません。


「=>」はラムダ演算子と呼ばれていましたが、C# 6.0 以降では
ラムダ式だけでなく、式形式のメンバー定義にも使われるようになりました。
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/lambda-operator
解決済み
[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90425 ] / ▼[ 90430 ]
■90426 / 4階層)  Re[4]: 引数のあるメソッドをメソッドに渡す
□投稿者/ B.B (14回)-(2019/03/10(Sun) 09:36:16)
No90425 (魔界の仮面弁士 さん) に返信

> えぇと…それはラムダ式とは関係ないです。(^_^:
> Func<,> はジェネリックなデリゲート型ですね。

デリゲート型というのがあるんですね(;´Д`A ```


> Delegate 型を無くしたらイベントすら扱えなくなりますよね。
> delegate キーワードのことを言っているのでしょうか。

このサイトの一番下に書かれていますがdelegate キーワードのことなのかな
https://qiita.com/rawr/items/11790e9ea08a29d028a4

delegateやDelegateというワードが出てきたら全部スルーしていました。
勉強するとっかかりになりました、ありがとうございます
[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90426 ] / ▼[ 90442 ]
■90430 / 5階層)  Re[5]: 引数のあるメソッドをメソッドに渡す
□投稿者/ 魔界の仮面弁士 (2096回)-(2019/03/11(Mon) 10:40:39)
No90426 (B.B さん) に返信
>>えぇと…それはラムダ式とは関係ないです。(^_^:
>>Func<,> はジェネリックなデリゲート型ですね。
>
> デリゲート型というのがあるんですね(;´Д`A ```

「+=」演算子を使うと、一つのデリゲートに複数のメソッドグループを含めることもできます。(-= で削除)
イベントを割り当てる際にも使われますね。


// 「void Foo()」な呼び出しを表すデリゲート型を宣言
delegate void SampleDelegate();

private void InstanceMethod() { MessageBox.Show(nameof(InstanceMethod)); }
private static void StaticMethod() { MessageBox.Show(nameof(StaticMethod)); }

private void Form1_Load(object sender, EventArgs e)
{
 // ローカル関数
 void LocalFunction() { MessageBox.Show(nameof(LocalFunction)); };
 void ExpressionBodiedLocalFunction() => MessageBox.Show(nameof(ExpressionBodiedLocalFunction));

 // デリゲートインスタンス
 Action ActionInstance = () => MessageBox.Show(nameof(ActionInstance));
 MethodInvoker MethodInvokerInstance = () => MessageBox.Show(nameof(MethodInvokerInstance));


 // デリゲート型の変数を用意して、「+=」でつなぐ
 SampleDelegate methods = null;


 methods = delegate { MessageBox.Show("anonymous1"); }; // 匿名メソッド
 methods += delegate { MessageBox.Show("anonymous2"); }; // += で追加していける
 methods += () => MessageBox.Show("lambda"); // ラムダ式も渡せる
 methods += InstanceMethod;
 methods += StaticMethod;
 methods += LocalFunction;
 methods += ExpressionBodiedLocalFunction;
 // methods += ActionInstance; // これは NG
 // methods += MethodInvokerInstance; // これは NG
 methods += new SampleDelegate(ActionInstance); // これは OK
 methods += new SampleDelegate(MethodInvokerInstance); // これは OK


 // 割り当てられた呼び出しの数
 MessageBox.Show($"{methods.GetInvocationList().Length}", "呼び出しリストの数");

 // デリゲート呼び出し(各メソッドが登録順に呼び出される)
 methods();
}
[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90430 ] / 返信無し
■90442 / 6階層)  Re[6]: 引数のあるメソッドをメソッドに渡す
□投稿者/ B.B (15回)-(2019/03/11(Mon) 23:09:50)
No90430 (魔界の仮面弁士 さん) に返信

> 「+=」演算子を使うと、一つのデリゲートに複数のメソッドグループを含めることもできます

ありがとうございます。自分がやろうとしていることを読み取っていただき感謝です。勉強になります

[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90412 ] / ▼[ 90416 ]
■90413 / 1階層)  Re[1]: 引数のあるメソッドをメソッドに渡す
□投稿者/ キングダム (9回)-(2019/03/09(Sat) 12:39:39)
No90412 (B.B さん) に返信

int result = hogeMethod(i => i * 2);

private int hogeMethod(Func<int, int> func)
{
    int a = 10;
    return func(a);
}

こんな感じです

[ 親 90412 / □ Tree ] 返信 編集キー/

▲[ 90413 ] / 返信無し
■90416 / 2階層)  Re[2]: 引数のあるメソッドをメソッドに渡す
□投稿者/ B.B (12回)-(2019/03/09(Sat) 15:51:55)
2019/03/09(Sat) 16:23:08 編集(投稿者)

No90413 (キングダム さん) に返信
> ■No90412 (B.B さん) に返信
>
> int result = hogeMethod(i => i * 2);
>
> private int hogeMethod(Func<int, int> func)
> {
> int a = 10;
> return func(a);
> }
>
> こんな感じです

返答ありがとうございます

int result = hogeMethod(method1);
この部分は変えたくないのですが次の魔界の仮面弁士さんのレスを見て意味が分かりました。ありがとうございました
[ 親 90412 / □ Tree ] 返信 編集キー/


管理者用

- Child Tree -