2009-05-20 6 views
299

tôi đã thường xuyên gặp phải một lỗi như "không thể chuyển đổi từ 'phương pháp nhóm' thành 'string'" trong các trường hợp như:Nhóm phương pháp trong C# là gì?

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

tất nhiên có một lỗi đánh máy trong dòng cuối cùng vì tôi quên ngoặc gọi sau ToString. Biểu mẫu chính xác sẽ là:

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

Tuy nhiên tôi đã tự hỏi nhóm phương pháp là gì. Google không phải là một sự trợ giúp cũng không phải là MSDN.

+52

Phần 7.1 của đặc tả C# 3.0 định nghĩa "phương pháp nhóm". –

+1

Tôi đã đọc lỗi này ngay bây giờ là * bạn đã bỏ lỡ dấu ngoặc khi gọi phương thức *. – niico

Trả lời

279

Một nhóm phương pháp là tên cho một tập các phương pháp (mà có thể chỉ là một) - tức là về mặt lý thuyết phương pháp ToString có thể có nhiều quá tải (cộng với bất kỳ phương pháp khuyến nông): ToString(), ToString(string format), vv - vì thế ToString tự nó là một "nhóm phương pháp".

Nó thường có thể chuyển đổi nhóm phương thức thành đại biểu (đã nhập) bằng cách sử dụng độ phân giải quá tải - nhưng không phải với chuỗi vv; nó không có ý nghĩa.

Sau khi bạn thêm dấu ngoặc đơn, một lần nữa; quá tải độ phân giải kicks trong và bạn đã unambiguously xác định một cuộc gọi phương thức.

+6

Cách sử dụng điển hình của nhóm phương pháp là gì? Kể từ khi (vì vậy tôi hiểu) nó có cùng tên số lượng thông số và/hoặc các loại sẽ khác nhau. Vì vậy, bạn không thể gọi nhiều hơn một phương pháp từ nhóm phương pháp sử dụng nhóm. –

+23

Nó hoàn toàn là một thuật ngữ trình biên dịch cho "Tôi biết tên phương thức là gì, nhưng tôi không biết chữ ký"; nó không tồn tại trong thời gian chạy. AFAIK, việc sử dụng duy nhất của một nhóm phương pháp * bởi chính nó * (không có dấu ngoặc vv) là trong quá trình xây dựng đại biểu. –

+16

ECMA 334v4 §14.1: Nhóm phương pháp có thể được sử dụng trong biểu thức gọi (§14.5.5), được sử dụng trong biểu thức tạo đại biểu (§14.5.10.3) hoặc được chuyển đổi hoàn toàn thành loại đại biểu tương thích. Trong bất kỳ ngữ cảnh nào khác, một biểu thức được phân loại như là một nhóm phương thức gây ra lỗi biên dịch. –

16

Kết quả đầu tiên trong tìm kiếm MSDN của bạn nói:

Nhóm phương pháp xác định một phương pháp để gọi hoặc tập các phương pháp quá tải mà từ đó để chọn một phương pháp cụ thể để gọi

sự hiểu biết của tôi là về cơ bản bởi vì khi bạn chỉ viết someInteger.ToString, nó có thể là:

Int32.ToString(IFormatProvider) 

hoặc nó có thể tham khảo:

Int32.ToString() 

vì vậy nó được gọi là một nhóm phương pháp.

15

Chức năng ToString có nhiều quá tải - nhóm phương pháp sẽ là nhóm bao gồm tất cả các quá tải khác nhau cho hàm đó.

+1

Có, và vấn đề là nhóm phương pháp là một cấu trúc biên dịch. Trình biên dịch chọn quá tải phương thức theo ngữ cảnh nơi nhóm tin nhắn được sử dụng. Ví dụ: bạn không thể viết "var x = Foo;" (trong đó Foo là một nhóm phương pháp), trình biên dịch từ chối điều này ngay cả khi chỉ có một quá tải. – Rolf

140

Ngoài ra, nếu bạn đang sử dụng LINQ, bạn có thể làm điều gì đó giống như myList.Select(methodGroup).

Vì vậy, ví dụ, tôi có:

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

Thay vì tuyên bố một cách rõ ràng biến được sử dụng như thế này:

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

Tôi chỉ có thể bỏ qua tên của var:

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

Một khuyến nghị ReSharper là điều khiến tôi tìm kiếm nhóm phương pháp. Đây là những gì ReSharper đã kết thúc với một trong những biểu thức linq của tôi. –

+42

@a_hardin: ReWarper FTW! Tôi đã học được rất nhiều về LINQ nhờ Resharper. –

+1

Vì vậy, có bất kỳ bên xuống này? Tại sao một người "không" muốn làm theo cách này? – JCisar

17

Bạn có thể truyền nhóm phương pháp thành người được ủy quyền.

Chữ ký của đại biểu chọn 1 phương pháp trong nhóm.

Ví dụ này chọn sự quá tải ToString() mà phải mất một tham số chuỗi:

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

Ví dụ này chọn sự quá tải ToString() mà mất không tham số:

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