Apa itu grup metode dalam C #?

351

Saya sering mengalami kesalahan seperti "tidak dapat mengkonversi dari 'grup metode' ke 'string'" dalam kasus-kasus seperti:

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

tentu saja ada kesalahan ketik pada baris terakhir karena saya lupa tanda kurung sesudahnya ToString. Bentuk yang benar adalah:

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

Namun saya jadi bertanya-tanya apa itu grup metode. Google tidak banyak membantu atau MSDN .

Andrei Rînea
sumber
62
Bagian 7.1 dari spesifikasi C # 3.0 mendefinisikan "grup metode".
Eric Lippert
2
Saya membaca kesalahan ini sekarang saat Anda melewatkan tanda kurung saat memanggil metode .
niico
2
Jika Anda memiliki daftar tipe delegasi yang sesuai, seperti var list = new List<Func<string>>();, maka grup metode akan dapat digunakan, dan list.Add(someObject.ToString);akan berhasil.
Jeppe Stig Nielsen

Jawaban:

332

Sebuah kelompok metode adalah nama untuk set metode (yang mungkin hanya satu) - yaitu dalam teori ToStringmetode mungkin memiliki beberapa overloads (ditambah metode ekstensi): ToString(), ToString(string format), dll - maka ToStringdengan sendirinya adalah sebuah "kelompok metode".

Itu biasanya dapat mengonversi grup metode ke delegasi (diketik) dengan menggunakan resolusi overload - tetapi tidak ke string dll; itu tidak masuk akal.

Setelah Anda menambahkan tanda kurung, lagi; resolusi kelebihan menendang masuk dan Anda telah jelas mengidentifikasi panggilan metode.

Marc Gravell
sumber
6
Apa yang akan menjadi kegunaan khas grup metode? Karena (jadi saya mengerti) itu memiliki nama yang sama jumlah parameter dan / atau jenis akan berbeda. Jadi, Anda tidak dapat meminta lebih dari satu metode dari grup metode menggunakan grup.
Andrei Rînea
32
Ini murni istilah kompiler untuk "Saya tahu apa nama metode itu, tetapi saya tidak tahu tanda tangannya"; tidak memiliki keberadaan saat runtime. AFAIK, satu-satunya penggunaan metode-kelompok dengan sendirinya (tidak ada tanda kurung dll) adalah selama konstruksi delegasi.
Marc Gravell
20
ECMA 334v4 §14.1: Grup metode dapat digunakan dalam ekspresi-doa (§14.5.5), digunakan dalam ekspresi-penciptaan-delegasi (§14.5.10.3), atau secara implisit dikonversi ke tipe delegasi yang kompatibel. Dalam konteks lain, ekspresi yang dikelompokkan sebagai grup metode menyebabkan kesalahan waktu kompilasi.
Marc Gravell
1
Dukungan kovarian dan contravariance untuk grup metode memungkinkan untuk mencocokkan tanda tangan metode dengan tipe delegasi. Ini memungkinkan Anda untuk menetapkan kepada delegasi tidak hanya metode yang memiliki tanda tangan yang cocok, tetapi juga metode yang mengembalikan lebih banyak tipe turunan (kovarian) atau yang menerima parameter yang memiliki lebih sedikit tipe turunan (contravariance) daripada yang ditentukan oleh tipe delegasi. Untuk informasi lebih lanjut, lihat Ragam dalam Delegasi (C #) dan Menggunakan Varians dalam Delegasi (C #).
user2211290
162

Juga, jika Anda menggunakan LINQ, Anda tampaknya dapat melakukan sesuatu seperti myList.Select(methodGroup).

Jadi, misalnya, saya punya:

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

Alih-alih secara eksplisit menyatakan variabel yang akan digunakan seperti ini:

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

Saya bisa menghilangkan nama var:

public List<string> GetStringStuff()
{
    return something.getStringsFromSomewhere.Select(DoSomethingToMyString);
}
Kaeles
sumber
112
Rekomendasi ReSharper adalah apa yang membuat saya mencari grup metode. Inilah yang akhirnya dilakukan ReSharper terhadap salah satu ekspresi LINQ saya.
a_hardin
50
@a_hardin: ReSharper FTW! Saya belajar banyak tentang LINQ berkat Resharper.
Jason Down
3
Versi "lebih eksplisit" hanya membuat metode pembungkus yang pada dasarnya tidak berguna. Metode pembungkus anonim dan DoSomethingToMyString mengambil string dan mengembalikan string. Karakter "str => [...] (str)" hanyalah cruft yang diharapkan dapat dikompilasi oleh kompiler.
Grault
6
Kompiler tidak mengoptimalkan apa pun. Menggunakan ILDASM, Anda melihat bahwa versi eksplisit membuat metode anonim (implementasi lambda) dan meneruskannya ke Select (). Versi implisit melewati DoSomethingToMyString secara langsung.
Rolf
14
Mengingatkan saya pada return flag == true ? true : false(facepalm).
ErikE
24

Anda dapat membuat grup metode ke delegasi.

Tandatangan delegasi memilih 1 metode dari grup.

Contoh ini mengambil ToString()kelebihan yang mengambil parameter string:

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

Contoh ini mengambil ToString()kelebihan yang tidak memerlukan parameter:

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

Hasil pertama dalam pencarian MSDN Anda mengatakan:

Grup metode mengidentifikasi satu metode yang akan dipanggil atau kumpulan metode kelebihan beban untuk memilih metode tertentu untuk dipanggil

Pemahaman saya adalah bahwa pada dasarnya karena ketika Anda baru saja menulis someInteger.ToString, itu mungkin merujuk pada:

Int32.ToString(IFormatProvider) 

atau bisa juga merujuk ke:

Int32.ToString()

sehingga disebut kelompok metode.

oscarkuo
sumber
18

The ToStringfungsi memiliki banyak overloads - kelompok metode akan menjadi kelompok yang terdiri dari semua overloads yang berbeda untuk fungsi yang.

INFORMASI 1800
sumber
2
Ya, dan intinya adalah bahwa grup metode adalah konstruk waktu kompilasi. Kompiler memilih satu metode kelebihan menurut konteks di mana grup pesan digunakan. Misalnya: Anda tidak dapat menulis "var x = Foo;" (di mana Foo adalah grup metode), kompiler menolak ini bahkan jika hanya ada satu kelebihan.
Rolf