c# - 具有自引用类型约束的通用类

标签 c# generics

考虑以下代码:

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

Bar(this) 行导致以下编译器错误:
参数类型 Foo 不可分配给参数类型 T

T 被限制为 Foo 因为我希望派生类基本上告诉基类它们的类型,以便可以在事件回调中使用该类型,以便使实现者不必将回调参数转换为派生类型。

我可以看到代码并不能很好地工作,但我对如何正确地执行此操作有一点障碍,而不会以可用于任何旧事物的通用委托(delegate)结束。考虑到它似乎是递归的,我也不太确定为什么 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();
    }
}

最佳答案

你可以将 'this' 转换为 T:

Bar((T)this);

但是,如果您有以下内容,这将失败:

public class MyFoo : Foo<MyFoo> { }

public class MyOtherFoo : Foo<MyFoo> { }

因为“MyOtherFoo”不是“MyFoo”的实例。看看this由 Eric Lippert 发表,他是 C# 的设计者之一。

关于c# - 具有自引用类型约束的通用类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6618134/

相关文章:

java未经检查的转换

java - 在java中使用泛型类型

c# - 检测何时创建新的托管线程

c# - 使用 LINQ 排序

java - 使用通用与位置之间的区别

generics - 与 C# 8.0 可空引用类型结合时,是否可以为值或字符串类型声明泛型类型约束?

java - 如何将Java代码转换为不使用泛型?

c# - 使用 JToken.Parse 解析 JSON - 帮助我将一行代码从 C# 转换为 VB

c# - 将 Int32 转换为 24 位有符号整数

C# 输出参数与返回值