2012-01-11 45 views
2

(使用.NET 4.0) 好了,我有鑄造一般委託給另一同類型接口

private Dictionary<int, Action<IMyInterface, IMyInterface>> handler {get; set;} 

public void Foo<T, U>(Action<T, U> myAction) 
    where T : IMyInterface 
    where U : IMyInterface 
    { 
     // | This line Fails 
     // V 
     Action<IMyInterface, IMyInterface> anotherAction = myAction; 
     handler.Add(someInt, anotherAction); 
    } 

我試圖存儲在一個泛型集合委託,這樣我就可以把它背出來稍後調用它。 我該如何正確施放它?

回答

1

Welp ...看起來像我,我的朋友發現了一些工作。

public void Foo<T, U>(Action<T, U> myAction) 
    where T : IMyInterface 
    where U : IMyInterface 
    { 
     Action<IMyInterface, IMyInterface> anotherAction = (x, y) => eventHandler.Invoke((TSender)x, (TObject),y); 
     handler.Add(someInt, anotherAction); 
    } 

通過簡單的lambda換行,我們完成了我們所需的操作。

6

Action委託的通用參數是type-contravariant;它們不是類型協變的。因此,您可以通過少於特定類型,但不是 a 更多特定類型。

所以這個編譯:

protected void X() 
{ 
    Action<string> A = Foo; 
} 

void Foo(object s) { } 

但這並不:

protected void X() 
{ 
    Action<object> A = Foo; 
} 

void Foo(string s) { } 

由於T and U : IMyInterface,你的代碼是類似於第一個例子。

智能感知解釋它,而明確:(這裏的bigger version

enter image description here

0

我不認爲這是做你正在試圖完成的任務的類型安全的方式。在更新的問題,使用例如:

private Dictionary<int, Action<IMyInterface, IMyInterface>> handler {get; set;} 

public void Foo<T, U>(Action<T, U> myAction) 
    where T : IMyInterface 
    where U : IMyInterface 
    { 
     Action<IMyInterface, IMyInterface> anotherAction = (x, y) => myAction.Invoke((T)x, (U)y); 
     handler.Add(someInt, anotherAction); 
    } 

假設IMyInterface的和MyImplementation定義如下:

interface IMyInterface 
{ 
    void bar(); 
} 

class MyImplementation : IMyInterface 
{ 
    void IMyInterface.bar() 
    { 
     //Snip: Do the things 
    } 

    void nope() 
    { 
     //Snip: Do other things 
    } 
} 

class MySimplerImplementation : IMyInterface 
{ 
    void IMyInterface.bar() 
    { 
     //Snip: Do things 
    } 
} 

我們可以發現自己在以下情況:

void test() 
{ 
    //Create an action with a method that only MyImplementation implements 
    Action<MyImplementation, MyImplementation> forMyImplementationOnly = 
     (x, y) => x.nope(); 

    //Use Foo (defined in the example code above) to 'cast' this 
    //action and add it to the handler dictionary 
    Foo<MyImplementation, Myimplementation>(forMyImplementationOnly); 

    //Retrieve the action from the handler dictionary 
    Action<IMyInterface, IMyInterface> castedAction = handler[someInt]; 

    //Try running the action using MySimplerImplementation 
    castedAction(new MySimplerImplementation(), new MySimplerImplementation()); 

    //This code will fail because MySimplerImplementation 
    //can not be cast to MyImplementation. It does not even 
    //define the nope() method that your initial Action required 
} 

這是這個Action泛型是逆變的原因(您可以使用較少的特定類型,但不是更具體的類型)。