다음 코드가 있습니다.
Func<string, bool> comparer = delegate(string value) {
return value != "0";
};
그러나 다음은 컴파일되지 않습니다.
var comparer = delegate(string value) {
return value != "0";
};
컴파일러가 왜 그것을 알 수 Func<string, bool>
없습니까? 하나의 문자열 매개 변수를 사용하고 부울을 반환합니다. 대신 오류가 발생합니다.
암시 적으로 형식화 된 로컬 변수에 익명 메서드를 할당 할 수 없습니다.
나는 하나의 추측을 가지고 있으며 var 버전이 컴파일 된 경우 다음과 같은 경우 일관성이 부족합니다.
var comparer = delegate(string arg1, string arg2, string arg3, string arg4, string arg5) {
return false;
};
Func <>은 최대 4 개의 인수 (.NET 3.5에서는 사용중인 것) 만 허용하므로 위의 내용은 의미가 없습니다. 아마도 누군가가 문제를 분명히 할 수있을 것입니다. 감사.
답변
다른 사람들은 이미 의미 할 수 있는 가능한 많은 델리게이트 유형이 있다고 지적했습니다. 너무 특별 Func
해서 Predicate
또는 대신에 기본값이 될 가치가있는 것Action
또는 다른 가능성은? 그리고 람다의 경우 표현 트리 형식이 아닌 대리자 형식을 선택하려는 의도가 분명한 이유는 무엇입니까?
그러나 우리는 이것이 Func
특별 하다고 말할 수 있으며 유추 된 람다 또는 익명의 방법은 Func의 무언가 라고 말할 수 있습니다. 우리는 여전히 모든 종류의 문제가 있습니다. 다음과 같은 경우 어떤 유형의 유추를 원하십니까?
var x1 = (ref int y)=>123;
Func<T>
아무 것도 참조하는 유형 이 없습니다 .
var x2 = y=>123;
리턴 값은 알고 있지만 형식 매개 변수의 유형은 모릅니다. (또는 우리는? 반환은 int? long? short? 바이트입니까?)
var x3 = (int y)=>null;
반품 유형은 알 수 없지만 무효화 할 수는 없습니다. 리턴 유형은 모든 참조 유형 또는 널 입력 가능 값 유형일 수 있습니다.
var x4 = (int y)=>{ throw new Exception(); }
다시, 우리는 리턴 타입을 모른다. 그리고 이번에는 그것이 무효 가 될 수 있다.
var x5 = (int y)=> q += y;
그것은 void-returning statement lambda 또는 q에 할당 된 값을 반환하는 것입니까? 둘 다 합법적입니다. 우리는 어느 것을 선택해야합니까?
자, 당신은 그 기능들을 지원하지 않는다고 말할 것입니다. 유형을 해결할 수있는 “일반적인”경우 만 지원하십시오. 도움이되지 않습니다. 어떻게하면 내 인생이 더 쉬워 집니까? 이 기능이 가끔 작동하고 가끔 실패하는 경우에도 이러한 모든 실패 상황 을 감지 하고 각각에 대해 의미있는 오류 메시지 를 표시 하는 코드를 작성해야합니다 . 우리는 여전히 모든 행동을 명시하고, 문서화하고, 테스트를 작성해야합니다. 이것은 매우 비싼 기능입니다 은 사용자가 약 6 번의 키 입력을 줄일 수 입니다. 우리는 절반의 시간 동안 작동하지 않고 작동하는 경우 거의 이점을 제공하지 않는 기능에 대해 테스트 케이스를 작성하는 데 많은 시간을 소비하는 것보다 언어에 가치를 더하는 더 좋은 방법이 있습니다.
실제로 유용한 상황은 다음과 같습니다.
var xAnon = (int y)=>new { Y = y };
해당 “말할 수있는”유형이 없기 때문입니다. 그러나 우리는 항상이 문제가 있으며 유형을 추론하기 위해 메소드 유형 유추를 사용합니다.
Func<A, R> WorkItOut<A, R>(Func<A, R> f) { return f; }
...
var xAnon = WorkItOut((int y)=>new { Y = y });
그리고 이제 메소드 타입 추론은 func 타입이 무엇인지 알아냅니다.
답변
Eric Lippert만이 확실하게 알고 있지만 위임 유형의 서명이 유형을 고유하게 결정하지 않기 때문이라고 생각합니다.
귀하의 예를 고려하십시오.
var comparer = delegate(string value) { return value != "0"; };
여기에 대한 두 가지 가능한 추론이 있습니다. var
이 있습니다.
Predicate<string> comparer = delegate(string value) { return value != "0"; }; // okay
Func<string, bool> comparer = delegate(string value) { return value != "0"; }; // also okay
컴파일러는 어느 것을 추론해야합니까? 둘 중 하나를 선택해야 할 이유가 없습니다. 그리고 a Predicate<T>
는 기능적으로 a와 동일 하지만 Func<T, bool>
.NET 유형 시스템 수준에서 여전히 다른 유형입니다. 따라서 컴파일러는 대리자 형식을 명확하게 확인할 수 없으므로 형식 유추에 실패해야합니다.
답변
에릭 Lippert의 오래된이 후 그는 말한다 곳에 약을
실제로 C # 2.0 사양에서는이를 호출합니다. 메소드 그룹 표현식 및 익명 메소드 표현식은 C # 2.0에서 유형이없는 표현식이며 람다 표현식은 C # 3.0에서이를 결합합니다. 그러므로 그들이 암묵적 선언의 오른쪽에 “나체”로 나타나는 것은 불법입니다.
답변
다른 대표는 다른 유형으로 간주됩니다. 예를 들어, Action
와 다르고 MethodInvoker
의 인스턴스 Action
를 유형의 변수에 할당 할 수 없습니다 MethodInvoker
.
그래서, 익명의 대표 (또는 람다) 등의 주어진 () => {}
, 그것에게 인 Action
또는를 MethodInvoker
? 컴파일러가 말할 수 없습니다.
마찬가지로, string
인수를 받아서를 반환 하는 대리자 형식을 선언 bool
하면 컴파일러 Func<string, bool>
가 내 대리자 형식 대신 실제로 원하는 것을 어떻게 알 수 있습니까? 델리게이트 유형을 유추 할 수 없습니다.
답변
다음은 암시 적으로 형식이 지정된 로컬 변수에 관한 MSDN의 요점입니다.
- var는 로컬 변수가 동일한 명령문에서 선언되고 초기화 될 때만 사용할 수 있습니다. 변수는 널 또는 메소드 그룹 또는 익명 함수로 초기화 될 수 없습니다.
- var 키워드는 컴파일러에게 초기화 명령문의 오른쪽에있는 표현식에서 변수 유형을 유추하도록 지시합니다.
- var 키워드는 “variant”를 의미하지 않으며 변수가 느슨하게 입력되었거나 늦게 묶여 있음을 나타내지 않습니다. 단지 컴파일러가 가장 적합한 유형을 결정하고 할당한다는 의미입니다.
MSDN 참조 : 암시 적으로 형식이 지정된 로컬 변수
익명 방법에 대해 다음을 고려하십시오.
- 익명 메소드를 사용하면 매개 변수 목록을 생략 할 수 있습니다.
익명 메소드에는 실제로 다른 메소드 서명이있을 수 있으므로 컴파일러는 할당 할 가장 적합한 유형을 올바르게 추론 할 수 없습니다.
답변
내 게시물은 실제 질문에 대답하지 않지만 다음과 같은 근본적인 질문에 대답합니다.
“어떻게 애매 모호한 유형을 입력하지 않아도 Func<string, string, int, CustomInputType, bool, ReturnType>
되는가?”[1]
내가 게으른 / 해킹 프로그래머이기 때문에 나는 Func<dynamic, object>
-단일 입력 매개 변수를 사용하고 객체를 반환하는-를 .
여러 인수에 대해 다음과 같이 사용할 수 있습니다.
dynamic myParams = new ExpandoObject();
myParams.arg0 = "whatever";
myParams.arg1 = 3;
Func<dynamic, object> y = (dynObj) =>
{
return dynObj.arg0.ToUpper() + (dynObj.arg1 * 45); //screw type casting, amirite?
};
Console.WriteLine(y(myParams));
팁 : 사용할 수 있습니다 Action<dynamic>
객체를 반환 할 필요가없는 경우 .
네, 아마도 프로그래밍 원칙에 위배된다는 것을 알고 있습니다.
나는 대의원에서 초심자입니다 … 내가 배운 것을 나누고 싶었습니다.
[1] 이것은 미리 정의 된 Func
매개 변수 를 요구하는 메서드를 호출하지 않는 것으로 가정합니다 . 이 경우 해당 문자열을 입력해야합니다.
답변
어때요?
var item = new
{
toolisn = 100,
LangId = "ENG",
toolPath = (Func<int, string, string>) delegate(int toolisn, string LangId)
{
var path = "/Content/Tool_" + toolisn + "_" + LangId + "/story.html";
return File.Exists(Server.MapPath(path)) ? "<a style=\"vertical-align:super\" href=\"" + path + "\" target=\"_blank\">execute example</a> " : "";
}
};
string result = item.toolPath(item.toolisn, item.LangId);