What is a method group in C#?
Asked Answered
T

5

410

I have often encountered an error such as "cannot convert from 'method group' to 'string'" in cases like:

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

of course there was a typo in the last line because I forgot the invocation parentheses after ToString. The correct form would be:

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

However I came to wonder what is a method group. Google isn't much of a help nor MSDN.

Tallyho answered 20/5, 2009 at 8:31 Comment(3)
Section 7.1 of the C# 3.0 specification defines "method group".Microsecond
I read this error now as you missed the brackets off when calling a method.Blowup
If you had had a list of an appropriate delegate type, such as var list = new List<Func<string>>();, then the method group would have been usable, and list.Add(someObject.ToString); would have worked.Engrain
S
386

A method group is the name for a set of methods (that might be just one) - i.e. in theory the ToString method may have multiple overloads (plus any extension methods): ToString(), ToString(string format), etc - hence ToString by itself is a "method group".

It can usually convert a method group to a (typed) delegate by using overload resolution - but not to a string etc; it doesn't make sense.

Once you add parentheses, again; overload resolution kicks in and you have unambiguously identified a method call.

Schild answered 20/5, 2009 at 8:35 Comment(5)
What would be typical uses of a method group? Since (so I understand) it has the same name the parameter count and/or types will differ. So you cannot invoke more than one method from the method group using the group.Felicidad
It is purely a compiler term for "I know what the method name is, but I don't know the signature"; it has no existence at runtime. AFAIK, the only use of a method-group by itself (no brackets etc) is during delegate construction.Schild
ECMA 334v4 §14.1: A method group can be used in an invocation-expression (§14.5.5), used in a delegate-creation-expression (§14.5.10.3), or implicitly converted to a compatible delegate type. In any other context, an expression classified as a method group causes a compile-time error.Schild
Covariance and contravariance support for method groups allows for matching method signatures with delegate types. This enables you to assign to delegates not only methods that have matching signatures, but also methods that return more derived types (covariance) or that accept parameters that have less derived types (contravariance) than that specified by the delegate type. For more information, see Variance in Delegates (C#) and Using Variance in Delegates (C#).Jesusa
100% of the time when I get this error, I forgot the brackets on the method call cause I thought it was a property. An error like "did you forget the ()" would actually be useful 99% of the time lolBlowup
C
192

Also, if you are using LINQ, you can apparently do something like myList.Select(methodGroup).

So, for example, I have:

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

Instead of explicitly stating the variable to be used like this:

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

I can just omit the name of the var:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}
Catlin answered 26/5, 2010 at 16:34 Comment(8)
A ReSharper recommendation is what led me to search for method group. This is what ReSharper ended up doing to one of my linq expressions.Himeji
@a_hardin: ReSharper FTW! I learned a lot about LINQ thanks to Resharper.Dahabeah
The "more explicit" version is only making an essentially useless wrapper method. The anonymous wrapper method and DoSomethingToMyString both take a string and return a string. The "str => [...](str)" characters are just cruft which the compiler hopefully optimizes away.Solothurn
The compiler optimizes nothing. Using ILDASM, you see that the explicit version creates a anonymous method (the lambda implementation) and passes it to Select(). The implicit version passes DoSomethingToMyString directly.Dieterich
Reminds me of return flag == true ? true : false (facepalm).Lavine
According to this test (vibrantcode.com/2013/02/19/lambdas-vs-method-groups) lambda appears to be faster, even though it creates an extra wrapper method.Becket
The relevant overload of Select wants a delegate of type Func<string, string> for its selector argument. This is exactly what method groups can be used for: Conversion into (compatible) delegate types.Engrain
@ErikE, updated link: Wayback Archive - vibrantcode.com/2013/02/19/lambdas-vs-method-groupsHeterocercal
F
39

You can cast a method group into a delegate.

The delegate signature selects 1 method out of the group.

This example picks the ToString() overload which takes a string parameter:

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

This example picks the ToString() overload which takes no parameters:

Func<string> fn = 123.ToString;
Console.WriteLine(fn);
Fibroblast answered 28/2, 2013 at 0:21 Comment(0)
B
22

The first result in your MSDN search said:

The method group identifies the one method to invoke or the set of overloaded methods from which to choose a specific method to invoke

my understanding is that basically because when you just write someInteger.ToString, it may refer to:

Int32.ToString(IFormatProvider) 

or it can refer to:

Int32.ToString()

so it is called a method group.

Barouche answered 20/5, 2009 at 8:36 Comment(0)
A
20

The ToString function has many overloads - the method group would be the group consisting of all the different overloads for that function.

Arratoon answered 20/5, 2009 at 8:36 Comment(1)
Yes, and the point is that a method group is a compile-time construct. The compiler chooses one method overload according to the context where the message group is used. For example: you cannot write "var x = Foo;" (where Foo is a method group), the compiler rejects this even if there is only one overload.Dieterich

© 2022 - 2024 — McMap. All rights reserved.