2012-01-11 150 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泛型是逆变的原因(您可以使用较少的特定类型,但不是更具体的类型)。