문제

C# 3.0 컴파일러가 왜 동일한 메소드에 대한 대의원을 암시 적으로 생성 할 수있을 때 매개 변수로 전달 될 때 메소드 유형을 추론 할 수없는 이유가 궁금합니다.

예는 다음과 같습니다.

class Test
{
    static void foo(int x) { }
    static void bar<T>(Action<T> f) { }

    static void test()
    {
        Action<int> f = foo; // I can do this
        bar(f); // and then do this
        bar(foo); // but this does not work
    }   
}

나는 내가 통과 할 수 있다고 생각했을 것이다 foo 에게 bar 컴파일러가 유형의 유형을 유추하게하십시오 Action<T> 전달되는 함수의 서명에서 이것은 작동하지 않습니다. 그러나 나는 만들 수있다 Action<int> ~에서 foo 캐스팅 없이는 컴파일러가 유형 추론을 통해 같은 일을 할 수 없다는 합법적 인 이유가 있습니까?

도움이 되었습니까?

해결책

어쩌면 이것은 더 명확하게 만들 것입니다 :

public class SomeClass
{
    static void foo(int x) { }
    static void foo(string s) { }
    static void bar<T>(Action<T> f){}
    static void barz(Action<int> f) { }
    static void test()
    {
        Action<int> f = foo;
        bar(f);
        barz(foo);
        bar(foo);
        //these help the compiler to know which types to use
        bar<int>(foo);
        bar( (int i) => foo(i));
    }
}

Foo는 행동이 아닙니다 - Foo는 방법 그룹입니다.

  • 할당 문에서 int 유형이 지정되어 있으므로 컴파일러는 어떤 FOO에 대해 말하는 FOO를 명확하게 알 수 있습니다.
  • Barz (FOO) 문서에서 int 유형이 지정되어 있으므로 컴파일러는 어떤 FOO에 대해 말하는 FOO를 알 수 있습니다.
  • BAR (FOO) 문서에서 단일 매개 변수가있는 FOO 일 수 있으므로 컴파일러가 포기할 수 있습니다.

편집 : 컴파일러가 유형을 파악하는 데 도움이되는 두 가지 (예 : 추론 단계를 건너 뛰는 방법)를 추가했습니다.

JSKEET의 답변에있는 기사를 읽은 후 유형을 추론하지 않기로 한 결정은 상호 추론 시나리오를 기반으로하는 것 같습니다.

  static void foo<T>(T x) { }
  static void bar<T>(Action<T> f) { }
  static void test()
  {
    bar(foo); //wut's T?
  }

일반적인 문제는 해결할 수 없었기 때문에 해결책이 해결되지 않은 특정 문제를 남기도록 선택합니다.

이 결정의 결과로, 당신은 방법에 대한 과부하를 추가하고 단일 멤버 메소드 그룹에 사용되는 모든 발신자로부터 많은 유형의 혼란을 얻지 못합니다. 좋은 일인 것 같아요.

다른 팁

추론은 유형이 확장되면 실패의 가능성이 없어야한다는 것입니다. 즉, 메소드 foo (문자열)가 유형에 추가되면 기존 메소드의 내용이 변경되지 않는 한 기존 코드에 중요하지 않습니다.

이러한 이유로 FOO가 하나만 있더라도 FOO (메소드 그룹이라고도 함)에 대한 참조는 유형이 아닌 대의원에게 캐스트 할 수 없습니다. Action<T> 그러나 다음과 같은 유형 별 대의원에만 Action<int>.

그것은 약간 이상합니다. 유형 추론에 대한 C# 3.0 사양은 읽기 어렵고 실수가 있지만 외모 작동해야합니다. 첫 번째 단계 (섹션 7.4.2.1)에서는 실수가 있다고 생각합니다. 첫 번째 총알에 메소드 그룹을 언급해서는 안됩니다 (명시 적 매개 변수 단용 추론 (7.4.2.7)으로 덮여 있지 않으므로 사용해야합니다. 출력 단용 추론 (7.4.2.6) 외모 그것이 작동하는 것처럼 - 그러나 분명히 그것은 그렇지 않습니다 :(

MS가 유형 추론의 사양을 개선하려고한다는 것을 알고 있으므로 조금 더 명확해질 수 있습니다. 또한 읽기가 어렵다는 점에 관계없이 메소드 그룹과 유형 추론에 제한이 있다는 것을 알고 있습니다. 방법 그룹이 실제로 단일 메소드 일 때 특수 사용될 수있는 제한 사항이 있습니다.

Eric Lippert에는 블로그 항목이 있습니다 방법 그룹과 함께 작동하지 않는 반환 단위 추론 그게 비슷한 이 경우 - 그러나 여기서 우리는 매개 변수 유형에만 리턴 유형에 관심이 없습니다. 가능합니다 그의 유형 추론 시리즈의 다른 게시물 그래도 도움이 될 수 있습니다.

임무를 명심하십시오

Action<int> f = foo;

이미 구문 설탕이 많이 있습니다. 컴파일러는 실제로이 명령문에 대한 코드를 생성합니다.

Action<int> f = new Action<int>(foo);

해당 메소드 호출은 문제없이 컴파일됩니다.

bar(new Action<int>(foo));

FWIW, 컴파일러가 유형 인수를 추론하는 데 도움이됩니다.

bar<int>(foo);

그래서 그것은 과제 진술서의 설탕이 왜 통화되지 않았는가? 설탕이 과제에 명백하지 않기 때문에 하나의 가능한 대체만이 있습니다. 그러나 메소드 호출의 경우 컴파일러 작성자는 이미 과부하 해상도 문제를 처리해야했습니다. 그 규칙은 매우 정교합니다. 그들은 아마 그것에 도달하지 않았을 것입니다.

완전성을 위해서는 C#에만 국한되지 않습니다. 동일한 vb.net 코드도 비슷하게 실패합니다.

Imports System

Module Test
  Sub foo(ByVal x As integer)
  End Sub
  Sub bar(Of T)(ByVal f As Action(Of T))
  End Sub

  Sub Main()
    Dim f As Action(Of integer) = AddressOf foo ' I can do this
    bar(f) ' and then do this
    bar(AddressOf foo) ' but this does not work
  End Sub
End Module

오류 BC32050 : 'public sub bar (t) (fs System.action (t))'에 대한 파라미터 't'유형을 추론 할 수 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top