5

을 감안할 때 두 가지 구현 :조건부 연산자와 비교 위임 비교 방법의

// compares by Key... 
private static int CompareByKey(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 

{ 
    return x.Key.CompareTo(y.Key); 
} 

// compares by Value... 
private static int CompareByValue(KeyValuePair<int, string> x, KeyValuePair<int, string> y) 
{ 
    return x.Value.CompareTo(y.Value); 
} 

것없는 다음과 같은 조건 연산자 코드 블록 컴파일 이유 :

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? CompareByKey : CompareByValue; 

컴파일러 오류 : "조건식의 종류는 할 수 없습니다 '방법 그룹'과 '방법 그룹'간에 암시 적 변환이 없기 때문에 결정할 수 있습니다.

그러나 if-else d를 사용하는 등가 코드 블록 히어로 어떤 문제가 없습니다 :

Comparison<KeyValuePair<int, string>> sortMethod; 
if (isSortByActualValue) 
    sortMethod = CompareByKey; 
else 
    sortMethod = CompareByValue; 

(위의 두 과제의 모든 좋은)

그래서 조건 연산자 내가 비교 위임 캐스트 경우, 수행합니다

Comparison<KeyValuePair<int, string>> sortMethod; 
sortMethod = isSortByActualValue ? (Comparison<KeyValuePair<int, string>>) CompareByKey : CompareByValue; 

합니다 (모든 좋은 캐스팅이 실제 부품에만있는 경우에도 캐스팅 한 경우)

+2

CompareByAcutalValue 및 CompareByDisplayValue는 어떻게 정의됩니까? CompareByKey 및 CompareByValue에 대한 정의 만 표시합니다. –

+0

내 게시물의 코드 스 니펫이 명확하게 편집되었습니다. 나는 (메소드의) 이름을 부분적으로 만 변경했다는 것을 깨닫지 못했습니다. Thanks Eric, CompareByActualValue에 대한 모든 참조를 CompareByKey (및 CompareByDisplayValue를 CompareByValue)로 업데이트했습니다. – Arun

답변

7

오류 메쏘드는 실제로 모든 것을 말하지만 매우 직관적이지는 않습니다. 메서드를 호출하지 않고 메서드 이름을 사용하면 메서드 그룹을 처리하는 것입니다. "group". 메서드가 오버로드 될 수 있고 이름이 오버로드 된 메서드 중 하나를 나타낼 수 있기 때문입니다.

이제 메서드 그룹은 서명이 일치하는 대리인에게 암시 적으로 변환 될 수 있으므로 if에 할당 된 이유가 여기에 해당됩니다.

지금까지 그렇게 좋았습니다. 그러나 조건 연산자 ?:은 두 번째와 세 번째 인수가 암시 적으로 변환 될 수있는 공통 유형을 추론해야하며 모든 변환을 고려하지는 않습니다 (이것은 여러 가지 문제점이 있음). 두 인수의 유형이 같은지 또는 암시 적으로 다른 인수로 변환 할 수 있는지 여부 만 확인합니다.

두 인수가 모두 메서드 그룹이지만 실제로는 다른 메서드 그룹의 고유 한 형식이며 하나의 메서드 그룹을 다른 것으로 변환 할 수 없습니다. 두 가지를 모두 대리자로 쉽게 변환 할 수는 있지만 컴파일러에서는이 사용을 금지합니다.

동일 방법에 의해, 다른 유형의 사실이다 :

object = someBool ? "" : New List<Integer>(); 

도 같은 이유로, 컴파일에 실패. 그리고 다시, 우리는이 명시 적으로 공통 기본 유형에 인수 중 하나를 주조하여 컴파일 할 수 있습니다 : 당신이 당신의 CompareByKey 같은 표현이있는 경우

object = someBool ? (object) "" : New List<Integer>(); 
+1

+1하지만 두 번째와 세 번째 인수가 암시 적으로 변환 될 수있는 일반적인 형식을 추론해야 할 필요가 있으므로 "두 번째 및 세 번째 인수의 형식을 추론해야합니다."라는 메시지가 변경됩니다. – phoog

+0

왜 isSortByActualValue ? CompareByKey : CompareByKey' 컴파일? 그들은 같은 방법 그룹이 아닌가? – svick

+0

@svick 메서드 그룹과 관계없이 메서드 그룹에서 메서드 그룹으로의 변환이 없습니다. 나는 그것을 명확하게해야만했는데, 보통 유형에이 변환이 없기 때문에 다소 특별한 경우입니다. 어떻게 이것이 C# 명세에서 정확하게 설명되었는지 모르겠습니다. –

3

, 그것은 특정 닷넷 유형을 가지고 있지 않지만,이 특별한 유형의 "방법 그룹". 그 이유는 CompareByKey이라는 몇 가지 방법을 사용할 수 있기 때문이며 어떤 방법을 원하고 있는지 명확하지 않습니다 (단 하나의 방법을 사용하더라도 정확히 동일하게 작동합니다). 또한 델리게이트 유형이 무엇을 원하는지 불분명합니다. Comparison<KeyValuePair<int, string>> 또는 Func<KeyValuePair<int, string>, int>입니다.

방법 그룹으로 무엇을 할 수 있습니까? 이를 사용하여 명시 적으로 대리자 (new Comparison<KeyValuePair<int, string>>(CompareByKey))를 만들 수 있으며 암시 적으로 대리자로 변환 할 수도 있습니다. 이것이 귀하의 if 버전이 작동하는 이유입니다.

그래서 문제가 무엇입니까? 조건부 연산자를 사용하는 경우 컴파일러는 전체 식의 형식을 알아야하며 할당 한 변수의 형식을 사용할 수 없습니다 (C#에서 형식 유추가 작동하는 방식이 아닙니다). 두 표현식은 모두 메소드 그룹이므로 메소드 그룹은 암시 적 변환없이 서로 다른 유형으로 처리되므로 전체 표현식의 유형을 판별 할 수 없습니다. 그래서 오류가 발생합니다.

조건부 연산자를 사용하지 않거나 캐스트 (또는 대리자 생성자)를 사용하여 명시 적으로 피연산자 중 하나의 형식을 지정하면 수정 프로그램을 발견했습니다.