C#のメソッドグループとは何ですか?


351

次のような場合、「「メソッドグループ」から「文字列」に変換できない」などのエラーが頻繁に発生します。

var list = new List<string>();
// ... snip
list.Add(someObject.ToString);

もちろん、最後の行にタイプミスがあったのは、後で括弧を忘れてしまったためToStringです。正しい形式は次のとおりです。

var list = new List<string>();
// ... snip
list.Add(someObject.ToString()); // <- notice the parentheses

でもメソッドグループってなに?グーグルはあまり助けでもなければMSDNでもない。


62
C#3.0仕様のセクション7.1では、「メソッドグループ」が定義されています。
Eric Lippert、

2
メソッドを呼び出すときに角かっこを逃したので、今このエラーを読みました。
niico

2
などの適切なデリゲートタイプのリストがあった場合var list = new List<Func<string>>();、メソッドグループは使用可能であり、機能list.Add(someObject.ToString);していました。
Jeppe Stig Nielsen

回答:


332

メソッドグループは、の名前であるメソッドのセット(その1つだけかもしれない) -すなわち理論的にはToStringこの方法は、複数のオーバーロード(プラス任意の拡張メソッド)を持っている可能性がありますToString()ToString(string format)など-ので、ToStringそれ自体で「メソッド・グループ」です。

通常、オーバーロード解決を使用してメソッドグループを(型付き)デリゲートに変換できますが、文字列などには変換できません。意味がありません。

かっこを追加したら、もう一度。オーバーロードの解決が始まり、メソッド呼び出しが明確に識別されました。


6
メソッドグループの一般的な用途は何ですか?(私が理解しているように)同じ名前であるため、パラメーターの数やタイプは異なります。したがって、グループを使用してメソッドグループから複数のメソッドを呼び出すことはできません。
AndreiRînea2009年

32
これは、「メソッド名はわかっているが、シグネチャがわからない」という純粋なコンパイラ用語です。実行時には存在しません。AFAIK、メソッドグループの単独での使用(ブラケットなどなし)は、デリゲートの構築中のみです。
Marc Gravell

20
ECMA 334v4§14.1:メソッドグループは、invocation-expression(§14.5.5)で使用したり、delegate-creation-expression(§14.5.10.3)で使用したり、互換性のあるデリゲート型に暗黙的に変換したりできます。その他のコンテキストでは、メソッドグループとして分類された式はコンパイル時エラーを引き起こします。
Marc Gravell

1
メソッドグループの共分散および反分散のサポートにより、メソッドシグネチャをデリゲート型と照合できます。これにより、シグネチャが一致するメソッドだけでなく、デリゲート型で指定されたものよりも多くの派生型(共分散)を返すメソッドや、デリバティブ型が少ないパラメーター(反分散)を受け入れるメソッドもデリゲートに割り当てることができます。詳細については、「デリゲートでの分散(C#)」および「デリゲートでの分散の使用(C#)」を参照してください。
user2211290 2017年

162

また、LINQを使用している場合は、明らかに次のようなことができますmyList.Select(methodGroup)

したがって、たとえば、私は持っています:

private string DoSomethingToMyString(string input)
{
    // blah
}

このように使用する変数を明示的に述べる代わりに:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(str => DoSomethingToMyString(str));
}

varの名前は省略できます。

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}

112
ReSharperの推奨事項により、メソッドグループを検索することになりました。これが、ReSharperが私のlinq式の1つに対して行った結果です。
a_hardin 2010

50
@a_hardin:ReSharper FTW!Resharperのおかげで、LINQについて多くのことを学びました。
Jason Down、

3
「より明示的な」バージョンは、本質的に役に立たないラッパーメソッドを作成するだけです。匿名ラッパーメソッドとDoSomethingToMyStringはどちらも文字列を受け取り、文字列を返します。"str => [...](str)"文字は、コンパイラーが最適化してうまくいけば、ただの残骸です。
グラールト2013年

6
コンパイラーは何も最適化しません。ILDASMを使用すると、明示的なバージョンが匿名メソッド(ラムダ実装)を作成し、それをSelect()に渡すことがわかります。暗黙のバージョンはDoSomethingToMyStringを直接渡します。
Rolf

14
ことを思い出すreturn flag == true ? true : false(手のひらを顔に当てます)。
ErikE、2015

24

メソッドグループをデリゲートにキャストできます。

デリゲートシグネチャは、グループから1つのメソッドを選択します。

この例ToString()では、文字列パラメーターを受け取るオーバーロードを選択します。

Func<string,string> fn = 123.ToString;
Console.WriteLine(fn("00000000"));

この例ToString()では、パラメーターを取らないオーバーロードを選択します。

Func<string> fn = 123.ToString;
Console.WriteLine(fn());

21

MSDN検索の最初の結果は次のとおりです。

メソッドグループは、呼び出す1つのメソッド、または呼び出す特定のメソッドを選択するオーバーロードされたメソッドのセットを識別します。

私が理解しているのは、基本的に、を書くだけでsomeInteger.ToString

Int32.ToString(IFormatProvider) 

または、以下を参照できます。

Int32.ToString()

したがって、メソッドグループと呼ばれます。


18

ToString関数は、多くのオーバーロードを有する-メソッドグループは、その機能のためのすべての異なるオーバーロードの群であろう。


2
はい、要点は、メソッドグループはコンパイル時の構成要素であるということです。コンパイラは、メッセージグループが使用されるコンテキストに応じて、1つのメソッドオーバーロードを選択します。たとえば、「var x = Foo;」とは記述できません。(Fooはメソッドグループ)、オーバーロードが1つしかない場合でも、コンパイラはこれを拒否します。
Rolf
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.