Một nhóm phương pháp trong C # là gì?


351

Tôi thường gặp phải một lỗi như "không thể chuyển đổi từ 'nhóm phương thức' thành 'chuỗi'" trong các trường hợp như:

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

tất nhiên có một lỗi đánh máy ở dòng cuối cùng vì tôi đã quên các dấu ngoặc đơn sau đó ToString. Các hình thức 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 một nhóm phương pháp là gì. Google không giúp được gì nhiều cho MSDN .


62
Mục 7.1 của đặc tả C # 3.0 định nghĩa "nhóm phương thức".
Eric Lippert

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

2
Nếu bạn đã có một danh sách các loại đại biểu thích hợp, chẳng hạn như var list = new List<Func<string>>();, thì nhóm phương thức sẽ có thể sử dụng được và list.Add(someObject.ToString);sẽ hoạt động.
Jeppe Stig Nielsen

Câu trả lời:


332

Một nhóm phương pháp là tên cho một tập hợp các phương pháp (mà có thể chỉ là một) - tức là về mặt lý thuyết các ToStringphương pháp 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ế ToStringbởi chính nó là một "nhóm phương pháp".

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

Khi bạn thêm dấu ngoặc đơn, một lần nữa; giải quyết quá tải bắt đầu và bạn đã xác định rõ ràng một cuộc gọi phương thức.


6
Điều gì sẽ được sử dụng điển hình của một nhóm phương pháp? Vì (vì vậy tôi hiểu) nó có cùng tên, số tham số và / hoặ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 thức từ nhóm phương thức bằng cách sử dụng nhóm.
Andrei Rînea

32
Đây hoàn toàn là một thuật ngữ 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 phương pháp nhóm tự (không có dấu ngoặc vv) là quá trình xây dựng đại biểu.
Marc Gravell

20
ECMA 334v4 §14.1: Một nhóm phương thức 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 ngầm định thành loại ủy nhiệm tương thích. Trong bất kỳ bối cảnh nào khác, một biểu thức được phân loại là một nhóm phương thức gây ra lỗi thời gian biên dịch.
Marc Gravell

1
Hỗ trợ hiệp phương sai và chống đối với các nhóm phương thức cho phép khớp chữ ký phương thức với các kiểu đại biểu. Điều này cho phép bạn gán cho đại biểu không chỉ các phương thức có chữ ký phù hợp mà cả các phương thức trả về nhiều loại dẫn xuất hơn (hiệp phương sai) hoặc chấp nhận các tham số có loại dẫn xuất ít hơn (chống chỉ định) so với chỉ định của loại đại biểu. Để biết thêm thông tin, hãy xem Phương sai trong Đại biểu (C #) và Sử dụng Phương sai trong Đại biểu (C #).
dùng2211290

162

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

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

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

Thay vì nói 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);
}

112
Một đề xuất ReSharper là điều khiến tôi tìm kiếm nhóm phương thức. Đây là những gì ReSharper đã làm với một trong những biểu thức linq của tôi.
a_hardin

50
@a_hardin: ReSharper FTW! Tôi đã học được rất nhiều về LINQ nhờ Resharper.
Jason Xuống

3
Phiên bản "rõ ràng hơn" chỉ tạo ra một phương thức trình bao bọc vô dụng. Phương thức trình bao bọc ẩn danh và DoS SomethingToMyString đều lấy một chuỗi và trả về một chuỗi. Các ký tự "str => [...] (str)" chỉ là hành trình mà trình biên dịch hy vọng sẽ tối ưu hóa.
Grault 18/03/13

6
Trình biên dịch tối ưu hóa không có gì. Sử dụng ILDASM, bạn thấy rằng phiên bản rõ ràng tạo ra một phương thức ẩn danh (triển khai lambda) và chuyển nó tới Chọn (). Phiên bản ngầm chuyển trực tiếp DoS SomethingToMyString.
Rolf

14
Nhắc nhở tôi về return flag == true ? true : false(facepalm).
ErikE

24

Bạn có thể truyền một nhóm phương thức thành một đại biểu.

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

Ví dụ này chọn ToString()quá tải có tham số chuỗi:

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

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

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

21

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

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

Hiểu biết của tôi về cơ bản là vì khi bạn chỉ viết someInteger.ToString, nó có thể đề cập đến:

Int32.ToString(IFormatProvider) 

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

Int32.ToString()

vì vậy nó được gọi là nhóm phương thức.


18

Các ToStringchức năng 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 chức năng đó.


2
Có, và vấn đề là một nhóm phương thức là một cấu trúc thời gian biên dịch. Trình biên dịch chọn quá tải một phương thức theo ngữ cảnh nơi nhóm thông báo đượ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 thức), trình biên dịch sẽ từ chối điều này ngay cả khi chỉ có một quá tải.
Rolf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.