IT박스

익명 메소드를 var에 할당 할 수없는 이유는 무엇입니까?

itboxs 2020. 6. 25. 22:01
반응형

익명 메소드를 var에 할당 할 수없는 이유는 무엇입니까?


다음 코드가 있습니다.

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대신의 기본이 될 자격이 있음을 PredicateAction또는 다른 가능성은? 그리고 람다의 경우 표현 트리 형식이 아닌 대리자 형식을 선택하려는 의도가 분명한 이유는 무엇입니까?

그러나 우리는 이것이 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? 컴파일러가 말할 수 없습니다.

Similarly, if I declare a delegate type taking a string argument and returning a bool, how would the compiler know you really wanted a Func<string, bool> instead of my delegate type? It can't infer the delegate type.


The following points are from the MSDN regarding Implicitly Typed Local Variables:

  1. var can only be used when a local variable is declared and initialized in the same statement; the variable cannot be initialized to null, or to a method group or an anonymous function.
  2. The var keyword instructs the compiler to infer the type of the variable from the expression on the right side of the initialization statement.
  3. It is important to understand that the var keyword does not mean "variant" and does not indicate that the variable is loosely typed, or late-bound. It just means that the compiler determines and assigns the most appropriate type.

MSDN Reference: Implicitly Typed Local Variables

Considering the following regarding Anonymous Methods:

  1. Anonymous methods enable you to omit the parameter list.

MSDN Reference: Anonymous Methods

I would suspect that since the anonymous method may actually have different method signatures, the compiler is unable to properly infer what the most appropriate type to assign would be.


My post doesn't answer the actual question, but it does answer the underlying question of :

"How do I avoid having to type out some fugly type like Func<string, string, int, CustomInputType, bool, ReturnType>?" [1]

Being the lazy/hacky programmer that I am, I experimented with using Func<dynamic, object> - which takes a single input parameter and returns an object.

For multiple arguments, you can use it like so:

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));

Tip: You can use Action<dynamic> if you don't need to return an object.

Yeah I know it probably goes against your programming principles, but this makes sense to me and probably some Python coders.

I'm pretty novice at delegates... just wanted to share what I learned.


[1] This assumes that you aren't calling a method that requires a predefined Func as a parameter, in which case, you'll have to type that fugly string :/


How is about that?

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);

참고URL : https://stackoverflow.com/questions/4965576/why-cant-an-anonymous-method-be-assigned-to-var

반응형