请考虑以下代码:
abstract class Foo<T>
where T : Foo<T>, new()
{
void Test()
{
if(Bar != null)
Bar(this);
}
public event Bar<T> Bar;
}
delegate void Bar<T>(T foo)
where T : Foo<T>, new();
Run Code Online (Sandbox Code Playgroud)
该行Bar(this)导致以下编译器错误:
参数类型Foo <T>不能分配给参数类型T.
T被约束为Foo <T>,因为我希望派生类基本上告诉基类它们的类型,以便可以在事件回调中使用该类型,以便保存实现者不必将回调参数强制转换为派生类型.
我可以看到代码不能正常工作,但我对如何正确地执行此操作有一点阻塞,而不会使用可用于任何旧事物的泛型委托.我也不太确定为什么T约束不会产生编译错误,因为它似乎是递归的.
编辑
我觉得我需要澄清一下!这是一个新的例子,我希望会更清楚.请注意,下面的OnDuckReady事件处理程序会生成编译器错误.
如何让事件以正确的类型传递?
abstract class Animal<T>
where T : Animal<T>, new()
{
void Test()
{
if(AnimalReady != null)
AnimalReady(this);
}
public event AnimalHandler<T> AnimalReady;
}
delegate void AnimalHandler<T>(Animal<T> animal)
where T : Animal<T>, new();
class Duck : Animal<Duck>
{
public void FlyAway()
{
}
}
class Test
{
void Main()
{
Duck duck = new Duck();
duck.AnimalReady += OnDuckReady; // COMPILER ERROR
}
void OnDuckReady(Duck duck)
{
duck.FlyAway();
}
}
Run Code Online (Sandbox Code Playgroud)
eul*_*rfx 17
你可以把'this'强制转换为T:
Bar((T)this);
Run Code Online (Sandbox Code Playgroud)
但是,如果您有以下内容,则会失败:
public class MyFoo : Foo<MyFoo> { }
public class MyOtherFoo : Foo<MyFoo> { }
Run Code Online (Sandbox Code Playgroud)
因为'MyOtherFoo'不是'MyFoo'的实例.看看C#设计师之一Eric Lippert的这篇文章.