C # 4.0의 명명 된 인수 및 제네릭 형식 유추
저는 C # 4.0에서 메서드를 호출 할 때 하나 이상의 선택적 매개 변수를 "건너 뛰는"경우가 아니면 인수에 대한 이름을 제공해도 결과에 영향을 미치지 않는다는 가정하에 프로그래밍했습니다.
그래서 나는 다음과 같은 행동을 발견하고 조금 놀랐습니다.
를 취하는 메소드가 주어지면 Func<T>
실행하고 결과를 반환합니다.
public static T F<T>(Func<T> f)
{
return f();
}
위의 방법을 볼 수있는 또 다른 방법 :
static void Main()
{
string s;
F (명명 된 인수없이)를 호출하면 문제없이 컴파일됩니다.
s = F<string>(() => "hello world"); // with explicit type argument <string>
s = F(() => "hello world"); // with type inference
그리고 명명 된 인수를 사용할 때 ...
s = F<string>(f: () => "hello world");
... 명시 적 형식 인수를 사용하는 위의 코드 줄은 여전히 문제없이 컴파일됩니다. 당연히 ReSharper가 설치되어 있으면 "유형 인수 사양이 중복됩니다"라는 메시지가 표시됩니다.
그러나 유형 인수를 제거 할 때 ...
s = F(f: () => "hello world");
C # 컴파일러는 다음 오류를보고합니다.
'Program.F (System.Func)'메서드의 형식 인수는 사용법에서 유추 할 수 없습니다. 형식 인수를 명시 적으로 지정해보십시오.
명명 된 인수와 유형 추론 간의 상호 작용에 대한 논리적 설명이 있습니까?
이 동작이 언어 사양 어딘가에 문서화되어 있습니까?
나는 내가 주장의 이름을 지정할 필요가 전혀 없다는 것을 이해합니다. 그러나 내부 문서화 목적으로 메서드 호출에서 인수의 이름을 지정하는 것이 합리적이라고 생각하는 훨씬 더 복잡한 시나리오에서이 동작을 발견했습니다. 이 문제를 해결하는 방법을 묻지 않습니다. 나는 언어의 더 미세한 부분을 이해하려고 노력하고 있습니다.
더 흥미롭게 만들기 위해 다음은 모두 문제없이 컴파일된다는 것을 발견했습니다.
Func<string> func = () => "hello world";
s = F<string>(func);
s = F(func);
s = F<string>(f: func);
s = F(f: func);
}
그건 그렇고 나는 비 정적 방법으로 동일한 동작을 관찰했습니다. 여기서 예제를 좀 더 짧게 만들기 위해 정적 메서드를 사용하기로 선택했습니다.
추론은 컴파일의 많은 중첩 수준에서 작동하는 것이 아닙니다. 제공된 인수를 기반으로 한 추측입니다. 나는 컴파일러 작성자가 명명 된 매개 변수와 함께 논리를 추론하는 것을 고려하지 않았다고 생각합니다. 추상 구문 트리를 고려하면 논리는 동일하지만 F (() => "xyz")와 F (f : () => "xyz")는 컴파일러 관점에서 볼 때 서로 다른 추상 구문 트리입니다.
컴파일러 자체조차도 엄청난 규칙 세트를 가진 프로그램 인 컴파일러 디자이너가 놓친 규칙이라고 생각합니다. 하나의 규칙이 첫 번째 케이스와 일치하지만 두 번째 케이스와 일치하는 규칙이 없습니다. 개념적으로 옳을 수도 있지만 컴파일러는 프로그램 일 뿐이며 모든 규칙은 사람이 코딩 한 것입니다.
좋아, 다른 사람들이 결정했듯이 버그이며 Microsoft 에보 고해야합니다 !!
그냥 당신이 알려하고자하는 것입니다 C 번호에 버그 특정 (그리고 나는 그것이 심지어 비주얼 스튜디오에서 표준에는 Csc.exe 실패 않습니다 확인했다 @leppie). 명명 된 인수를 중복으로 지정해도 동작이 전혀 변경 되지 않아야 합니다.
Microsoft Connect 에서 버그가보고되었습니다 .
동등한 VB는 정상적으로 작동합니다 (컴파일을 수행하기 때문에 런타임 동작이 예상대로인지 확인하기 위해 약간 추가했습니다).
Imports System
Module Test
Function F(Of T)(ByVal fn As Func(Of T)) As T
Return fn()
End Function
Function Inc(ByRef i as Integer) As String
i += 1
Return i.ToString
End Function
Sub Main()
Dim s As String
s = F(Of String)(Function()"Hello World.")
console.writeline(s)
s = F(Function()"Hello, World!")
console.writeline(s)
s = F(Of String)(fn:=Function()"hello world.")
console.writeline(s)
s = F(fn:=Function()"hello world")
console.writeline(s)
Dim i As Integer
Dim func As Func(Of String) = Function()"hello world " & Inc(i)
s = F(Of string)(func)
console.writeline(s)
s = F(func)
console.writeline(s)
s = F(Of string)(fn:=func)
console.writeline(s)
s = F(fn:=func)
console.writeline(s)
End Sub
End Module
산출:
Hello World.
Hello, World!
hello world.
hello world
hello world 1
hello world 2
hello world 3
hello world 4
Calling a function with named parameters and without named parameters are not the same. In case of named parameters compiler takes different path since it needs to resolve the named parameters first. In your case compiler is trying to figure out parameter f before resolving the T in F so it is requesting the programmer to explicitly state that.
ReferenceURL : https://stackoverflow.com/questions/6542822/named-arguments-and-generic-type-inference-in-c-sharp-4-0
'program story' 카테고리의 다른 글
Python 모듈 종속성이있는 Python 소프트웨어를 쉽게 배포하는 방법은 무엇입니까? (0) | 2020.12.26 |
---|---|
서버에서 HEIF (.heic)를 JPEG로 변환 하시겠습니까? (0) | 2020.12.26 |
매크로를 사용한 훌륭한 응용 프로그램 및 프로그램 모음 (0) | 2020.12.26 |
CQRS : 명령 반환 값 (0) | 2020.12.26 |
C ++ 로깅 프레임 워크 제안 (0) | 2020.12.26 |