2010-06-20 1 views
1
class MyClass 
{ 
    public event Action<string> OnAction; 
    public event Func<string, int> OnFunc; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     MyClass mc = new MyClass(); 

     /// I need to handle arbitrary events. 
     /// But I see no way to create anonymous delegates in runtime 
     /// with arbitrary returns and parameters. So I choosed to 
     /// create multiple “signatures” with different parameter 
     /// number (up to 10) and different returns (either the Action or 
     /// Func). While Actions<> work pretty well, the Funcs<> do not. 
     Action<dynamic> someAction = delegate(dynamic p1) { }; 
     Func<dynamic, dynamic> someFunc = delegate(dynamic p1) { return 42;}; 

     // OK 
     mc.OnAction += someAction; 

     // Error: “Cannot implicitly convert type 'System.Func<dynamic,dynamic>' 
     // to 'System.Func<string,int>'” 
     mc.OnFunc += someFunc; 

     // It doesn't work this way as well (the same error message): 
     // dynamic someFunc = new Func<dynamic, dynamic>((dynamic n1) => { return 42; }); 

     // Let's try another way 
     // 1: 
     // Cannot convert anonymous method to delegate type 'System.Func<string,int>' 
     // because the parameter types do not match the delegate parameter types. 
     // 2 (even more funny): 
     // Parameter 1 is declared as type 'dynamic' but should be 'string'. 
     mc.OnFunc += delegate(dynamic p1) { return 42; }; 
    } 
} 

조치에 대해 작동하고 기능에 대해 작동하지 않는 이유는 무엇입니까? 다른 말로하면 이 괜찮 으면 Func<dynamic,dynamic> → Func<string, int>이 아닌 이유를 알고 싶습니다. 감사..NET4 : 반환과 함께 익명의 대리자에 동적 바인딩을 적용하는 방법?

답변

0

Action과 Func 정의의 유일한 차이점은 Action에 반환 유형이 없음을들 수 있습니다. 당신의 코드를 변경하는 경우 :

mc.OnFunc += new Func<dynamic, dynamic>(someFunc);// += someFunc; 

mc.OnFunc += new Func<dynamic, int>(someFunc);// += someFunc; 

로 작동합니다.

+0

하지만 그럴 수 없습니다. 나는 보편적 인 해결책이 필요하다. – Yegor

+0

@Entrase, 보편적 인 해결책과 같은 것은 없습니다 ... 보편적 인 답을 찾으려면 42입니다.) –

+0

상황에 처하게하십시오. 나는 삶의 의미를 찾고 있지 않습니다. 나는 단지 이유를 알고 싶습니다. → Func → Func 은 동작하지 않습니다. → 작업은 정상입니다. 알고 계시다면 알려주세요. – Yegor

1

C#에서 반환 형식이 int 인 대리자가 필요하면 dynamic을 반환하도록 지정된 대리자는 호환되지 않습니다. 대리자는 Func<dynamic, dynamic>으로 선언되며 C#은 강력한 형식입니다. 함수가 실제로 int를 반환하고 문자열을 받는지 상관하지 않습니다. 여전히 Func<dynamic, dynamic>으로 선언되어 있습니다.

이 예를 고려한다면 코드가 분명하다 컴파일되지 않는 이유 :

Func<string, int> myFunc = delegate(string foo) { return 42; };  
int result = myFunc("Foo"); 

// If this was allowed... 
Func<dynamic, dynamic> otherFunc = delegate(string foo) { return 42; }; 
myFunc = otherFunc; 
result = myFunc("Foo"); 

// Then this would also be allowed but would be a run-time error. 
otherFunc = delegate(string foo) { return "Bar"; }; // Valid 
myFunc = otherFunc; 
result = myFunc("Foo"); // Oops... an int isn't returned. 
+0

동적 바인딩/캐스팅이 매개 변수에서 작동하고 반품에 사용할 수없는 이유는 무엇입니까? – Yegor

0

좋아, 나는 그것을 얻었다. delegate void Action <in T> (T arg); FUNC가 같이있는 동안 : 다음과 같이

액션은 정의 delegate TResult Func <in T, out TResult> (T arg); 문제는 공분산을 표시하지만 에서 키워드처럼 contravariance하지 밖으로 키워드입니다. 동시에 typeof(dynamic) == typeof(object)이 참입니다. 그래서 동적 인은 좀 더 일반적인 유형으로서 우리가 취하는 모든 것과 공변하지 않습니다. 흠, 내가 동적 바인딩 생각은 더 유연 "

추가 읽기 :. http://blogs.msdn.com/b/csharpfaq/archive/2010/02/16/covariance-and-contravariance-faq.aspx

, BTW 견적 내가 나중에 그곳에서 발견 :이 경우

당신은 공변로 제네릭 형식 매개 변수를 표시 할 수 있습니다 메서드 반환 형식으로 만 사용되며 형식 메서드 매개 변수의 형식으로 사용되지 않습니다. 그 반대의 경우도, 형식을 형식적 메서드 매개 변수 유형으로 만 사용하고 메서드 반환 형식으로 사용하지 않으면 반올림 형식으로 표시 할 수 있습니다.

관련 문제