C #의 메소드 그룹은 무엇입니까?


351

다음과 같은 경우에 " 'method group'에서 'string'으로 변환 할 수 없습니다"와 같은 오류가 종종 발생했습니다.

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
C # 3.0 사양의 섹션 7.1은 "방법 그룹"을 정의합니다.
Eric Lippert

2
메소드를 호출 할 때 대괄호를 놓치면서이 오류를 읽었 습니다 .
niico

2
과 같은 적절한 대리자 유형의 목록이있는 경우 var list = new List<Func<string>>();메소드 그룹을 사용할 수 있고 list.Add(someObject.ToString);작동했을 것입니다.
Jeppe Stig Nielsen 's

답변:


332

방법 그룹이의 이름입니다 방법의 설정 (즉, 하나의 수도)를 - 즉 이론의 ToString방법은 여러 오버로드 (플러스 어떤 확장 메서드)를 가질 수 : 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
메소드 그룹에 대한 공분산 및 반 분산 지원은 메소드 서명을 대리자 유형과 일치시킬 수 있습니다. 이를 통해 일치하는 서명이있는 메소드뿐만 아니라 더 많은 파생 유형 (공분산)을 리턴하거나 파생 유형 (비 분산)이 더 적은 매개 변수를 대리자 유형으로 지정된 메소드를 허용하는 메소드도 대리자에게 지정할 수 있습니다. 자세한 내용은 대리인의 변형 (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! Resharper 덕분에 LINQ에 대해 많은 것을 배웠습니다.
Jason Down

3
"보다 명시적인"버전은 본질적으로 쓸모없는 래퍼 방법 만 만들고 있습니다. 익명 래퍼 메서드와 DoSomethingToMyString은 모두 문자열을 사용하여 문자열을 반환합니다. "str => [...] (str)"문자는 컴파일러가 절실히 최적화하는 쪼그리고 앉는 것입니다.
Grault

6
컴파일러는 아무것도 최적화하지 않습니다. ILDASM을 사용하면 명시 적 버전이 익명 메소드 (람다 구현)를 작성하여 Select ()에 전달 함을 알 수 있습니다. 암시 적 버전은 DoSomethingToMyString을 직접 전달합니다.
Rolf

14
나에게 return flag == true ? true : false(얼굴 손바닥)을 상기시킵니다.
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기능은 많은 과부하가 있습니다 - 메소드 그룹이 그 함수에 대한 모든 다른 과부하로 구성된 그룹이 될 것입니다.


2
예, 요점은 메소드 그룹이 컴파일 타임 구성이라는 것입니다. 컴파일러는 메시지 그룹이 사용되는 컨텍스트에 따라 하나의 메소드 오버로드를 선택합니다. 예를 들어 "var x = Foo;"라고 쓸 수 없습니다. (Foo가 메소드 그룹 인 경우) 컴파일러는 과부하가 하나만 있어도이를 거부합니다.
Rolf
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.