กลุ่มวิธีใน 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

อย่างไรก็ตามฉันมาสงสัยว่ากลุ่มวิธีคืออะไร Googleไม่มากของความช่วยเหลือที่มิได้MSDN


62
ส่วนที่ 7.1 ของข้อกำหนด C # 3.0 กำหนด "กลุ่มวิธี"
Eric Lippert

2
ฉันอ่านข้อผิดพลาดนี้ในขณะนี้เป็นที่คุณพลาดวงเล็บปิดเมื่อเรียกวิธีการ
niico

2
หากคุณมีรายการประเภทตัวแทนที่เหมาะสมเช่นvar list = new List<Func<string>>();กลุ่มวิธีจะใช้งานได้และlist.Add(someObject.ToString);จะได้ผล
Jeppe Stig Nielsen

คำตอบ:


332

กลุ่มวิธีการคือชื่อสำหรับชุดของวิธีการ (ที่อาจจะมีเพียงหนึ่ง) - คือในทฤษฎีToStringวิธีการอาจจะมีหลาย overloads (บวกวิธีการขยายใด ๆ ) ToString(), ToString(string format)ฯลฯ - เพราะฉะนั้นToStringโดยตัวเองเป็นกลุ่ม "วิธีการ"

มันสามารถแปลงกลุ่มวิธีเป็นตัวแทน (พิมพ์) โดยใช้การแก้ปัญหาการโอเวอร์โหลด มันไม่สมเหตุสมผล

เมื่อคุณเพิ่มวงเล็บอีกครั้ง; ความละเอียดเกินพิกัดจะเริ่มทำงานและคุณได้ระบุวิธีการโทรอย่างไม่น่าสงสัย


6
อะไรคือการใช้งานทั่วไปของกลุ่มวิธี เนื่องจาก (ดังนั้นฉันเข้าใจ) มันมีชื่อเดียวกันจำนวนพารามิเตอร์และ / หรือประเภทจะแตกต่างกัน ดังนั้นคุณไม่สามารถเรียกใช้มากกว่าหนึ่งวิธีจากกลุ่มวิธีโดยใช้กลุ่ม
Andrei Rînea

32
มันเป็นคำแปลอย่างหมดจดสำหรับ "ฉันรู้ว่าชื่อวิธีคืออะไร แต่ฉันไม่รู้จักลายเซ็น"; มันไม่มีที่รันไทม์ AFAIK การใช้กลุ่มวิธีด้วยตัวเองเท่านั้น (ไม่มีวงเล็บเหลี่ยม ฯลฯ ) อยู่ระหว่างการสร้างผู้รับมอบสิทธิ์
Marc Gravell

20
ECMA 334v4 §14.1: กลุ่มวิธีสามารถใช้ในการเรียกใช้นิพจน์ (§14.5.5) ที่ใช้ในการสร้างผู้รับมอบสิทธิ์สร้างนิพจน์ (§14.5.10.3) หรือแปลงเป็นประเภทตัวแทนที่เข้ากันได้โดยปริยาย ในบริบทอื่นใดนิพจน์ที่จัดเป็นกลุ่มวิธีจะทำให้เกิดข้อผิดพลาดในการคอมไพล์
Marc Gravell

1
การสนับสนุนความแปรปรวนร่วมและความแปรปรวนสำหรับกลุ่มวิธีการช่วยให้สามารถจับคู่ลายเซ็นวิธีที่มีประเภทผู้ได้รับมอบหมาย สิ่งนี้ช่วยให้คุณสามารถมอบหมายให้ผู้รับมอบสิทธิ์ไม่เพียง แต่วิธีการที่มีลายเซ็นที่ตรงกัน แต่ยังวิธีการที่ส่งกลับประเภทที่ได้รับเพิ่มเติม (ความแปรปรวนร่วม) หรือที่ยอมรับพารามิเตอร์ที่มีประเภทที่ได้รับน้อยกว่า (contravariance) สำหรับข้อมูลเพิ่มเติมดูความแปรปรวนในผู้แทน (C #) และการใช้ความแปรปรวนในผู้แทน (C #)
user2211290

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 ของฉัน
a_hardin

50
@a_hardin: ReSharper FTW! ฉันได้เรียนรู้มากมายเกี่ยวกับ LINQ ขอบคุณ Resharper
เจสันลง

3
เวอร์ชั่น "ชัดเจนยิ่งขึ้น" กำลังสร้างวิธีการห่อหุ้มที่ไร้ประโยชน์โดยพื้นฐานเท่านั้น เมธอด wrapper ที่ไม่ระบุชื่อและ DoSomethingToMyString ใช้ทั้งสตริงและส่งคืนสตริง อักขระ "str => [... ] (str)" เป็นเพียง cruft ซึ่งคอมไพเลอร์หวังว่าจะปรับให้เหมาะสม
Grault

6
คอมไพเลอร์ไม่ทำอะไรเลย ใช้ ILDASM คุณจะเห็นว่ารุ่นที่ชัดเจนสร้างวิธีการที่ไม่ระบุชื่อ (การใช้แลมบ์ดา) และส่งผ่านไปยัง Select () รุ่นโดยนัยผ่าน DoSomethingToMyString โดยตรง
Rolf

14
เตือนฉันถึงreturn flag == true ? true : false(facepalm)
ErikE

24

คุณสามารถส่งกลุ่มวิธีเป็นผู้รับมอบสิทธิ์

ลายเซ็นผู้รับมอบสิทธิ์เลือก 1 วิธีจากกลุ่ม

ตัวอย่างนี้เลือกToString()โอเวอร์โหลดซึ่งใช้พารามิเตอร์สตริง:

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

ตัวอย่างนี้เลือกToString()โอเวอร์โหลดซึ่งไม่มีพารามิเตอร์:

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

21

ผลลัพธ์แรกในการค้นหา MSDN ของคุณกล่าวว่า:

กลุ่มวิธีการระบุวิธีการหนึ่งที่จะเรียกใช้หรือชุดของวิธีที่มากเกินไปที่จะเลือกวิธีเฉพาะที่จะเรียกใช้

ความเข้าใจของฉันก็คือโดยทั่วไปเพราะเมื่อคุณเพิ่งเขียนsomeInteger.ToStringมันอาจหมายถึง:

Int32.ToString(IFormatProvider) 

หรือสามารถอ้างถึง:

Int32.ToString()

ดังนั้นจึงเรียกว่ากลุ่มวิธี


18

ToStringฟังก์ชั่นที่มีการทับถมจำนวนมาก - กลุ่มวิธีการที่จะเป็นกลุ่มที่ประกอบด้วยทั้งหมด overloads แตกต่างกันสำหรับฟังก์ชั่นที่


2
ใช่และประเด็นก็คือกลุ่มวิธีการสร้างเวลารวบรวม คอมไพเลอร์เลือกหนึ่งเมธอดโอเวอร์โหลดตามบริบทที่ใช้กลุ่มข้อความ ตัวอย่างเช่น: คุณไม่สามารถเขียน "var x = Foo;" (โดยที่ Foo เป็นกลุ่มเมธอด) คอมไพเลอร์ปฏิเสธสิ่งนี้แม้ว่าจะมีเพียงโอเวอร์โหลดเดียวเท่านั้น
Rolf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.