2012-05-16 2 views
1

아래 코드에서는 Bar이라는 두 가지 오버로드 된 메서드를 정의했습니다. Foo()에서 나는 Bar으로 3 번 전화를 걸고 세 번째 전화에서 오류가 발생합니다.매개 변수 배열이있는 일반 C# 메서드 오버로드 해결

처음 두 개는 예상되는 과부하를 해결합니다. 분명히 세 번째 호출이 "() 바"에 바인딩하지만 예외에 첫 번째 매개 변수를 변환하는 데 실패

The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Bar<T>(T, string, params object[])'. There is no implicit reference conversion from 'string' to 'System.Exception'.

: 세 번째는 그러나 다음과 같은 오류를 생성합니다. 그것은 컴파일러를 버리는 문자열이라는 두 번째 인수라는 것도 분명합니다. 문자열이 아닌 경우 (케이스 2) 해상도가 좋습니다. 하지만 실패한 줄이 "Bar()"에 바인딩되어야한다는 것이 분명합니다 (첫 번째 매개 변수는 명확하게 문자열이므로).

컴파일러가이 바인딩을 사용하는 이유는 누구나 설명 할 수 있습니까? 나는 창조적 인 해결 방법을 고려할 것입니다. 그러나 제가 정말로 찾고있는 것은 왜 이것이 일어나고 있는지에 대한 설명입니다. C# 언어 사양으로 시간을 보냈지 만 명확한 대답을 찾지 못했습니다 (예 : 포기). 분명히 Bar 메서드 중 하나의 이름을 바꾸거나 명명 된 인수를 제공하거나 ref 매개 변수 중 하나를 표시 할 수는 있지만 이러한 특정 시나리오에는 이상적이지 않습니다.

아니지만 그것은 관련이 있지만 정확히이 일을 자바 코드를 작성하고 컴파일러는 아무런 문제가 없었다.

코드 :

public void Bar(string s, params object[] ps) { } // Call this "Bar()" 
public void Bar<E>(E e, string s, params object[] ps) where E : Exception { } // Call this "Bar<T>()" 

public void Foo() 
{ 
    Exception e; 
    Object o1, o2; 

    Bar(e, "fmt {0}", o); // Resolves fine, as expected 
    Bar("fmt {0} {2}", o1, o2); // Also resolves as expected 
    Bar("fmt {0} {2}", "bar", o1); // Error! 
} 
+0

유사 항목 : http://stackoverflow.com/questions/965423/c-sharp-generic-overload-compiler-cant-determine-correct-call – Travis

+0

하지만 그 질문은 모호성을 다루고 있습니다. 이 경우 컴파일러와 바인딩에 동의합니다. 우리는 어느 것에 동의하지 않습니다! – pamphlet

답변

4

대답은 과부하 매칭 제약을 고려하지 않는다는 것입니다. C# 스펙에서와 마찬가지로 완전히 확실하지 않습니다. 일치 검색은 항상 가장 구체적인 옵션과 문자열을 일반 문자로 사용합니다. T은 항상 문자열보다 Object (실제 유형 및 하위 유형과 일치하므로)보다 구체적입니다. Eric Lippert의 블로그 Constraints are not part of the signature을 참조하십시오.

이 작업을 수행하려면 예외 제한이 필요한 경우 가능한 경우 void Bar(Exception E, ...)을 사용하십시오.

+0

제약 조건이 무시된다는 것은 흥미 롭습니다. 그러나 문자열이 아닌 첫 번째 인수가 비 제네릭을 더 잘 일치시키지 않습니까? 내 말은, 실패 할 수있는 방법 대신 실패를 일으키는 방법에 구속력이 있다는 것입니다. 알아? – pamphlet

+1

첫 번째'Bar '의 두 번째 인수는 선택적 개체이므로 두 번째 일치하는 것이 더 구체적입니다. 'Bar (string은 T, string, ...)'는 Bar (string, Object, ...와 같은 문자열)보다 더 구체적입니다. 나는 당신이 다른 방법으로 그것을 고려할 수 있다고 생각하지만, 컴파일러 팀은 그것을 첫번째 방법으로 썼다. Eric Lippert (http://blogs.msdn.com/b/ericlippert/)는 그런 경우에 대해 말할 내용이있을 수 있습니다. 테이크 아웃 문자열'T'는 string보다 Object 만 사용합니다. – Travis

+3

@Travis 그가 그랬던 것처럼 보입니다. http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-theigns.aspx – climbage

2

Bar("fmt {0} {2}", "bar", o1); // 오류! 우선 순위 우선 순위에 따라 두 번째 매개 변수가 string 인 메서드 서명을 찾고 (String은 개체보다 더 구체적 임) 형식 인수를 확인하려고 시도하지만이를 수행 할 수 없습니다. 그것을 설명하기로 세 번째 전화를 교체하려고 :

Bar("fmt {0} {2}", (object)"bar", o1); // Now it is fine for compiler!