无法将X类型转换为T.泛型类中的泛型委托

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无法将X类型转换为T.泛型类中的泛型委托相关的知识,希望对你有一定的参考价值。

请考虑以下代码:

delegate void SomeDelegate<in T>(T foo) where T : Foo;

class Foo { }

class SomeGenericClass<T> where T:Foo
{
    private readonly SomeDelegate<T> _action = _ => Console.WriteLine("Foo");

    public void DoStuff()=> _action(new Foo()); //here is the compiler error
}

代码是不言自明的,我有这个空的Foo类。然后我使用泛型约束定义泛型委托,以便type参数始终为Foo。然后我们有一个简单的泛型类,其约束与委托相同,在其中我们有一个泛型委托字段。 DoStuff调用此委托并传递Foo的新实例。

为什么这不编译?我的意思是,我知道为什么,编译器告诉我:

CS1503参数1:无法从'ConsoleForSimpleTests.Program.Foo'转换为'T'

问题是:为什么编译器在定义了泛型约束的情况下无法将Foo转换为T?为什么这里需要明确的演员表?

假设我添加以下类:class Boo:Foo { }

我可以通过两种方式使事情发挥作用:

第一:我们将泛型委托字段明确地声明为Foo。在这种情况下,我甚至不需要SomeGenericClass中的泛型类型参数

class SomeGenericClass<T> where T:Foo
{
    private readonly SomeDelegate<Foo> _action = _ => Console.WriteLine("Foo");

    public void DoStuff()
    {
        _action(new Foo());
        _action(new Boo());
    }
}

第二:我们保留T,但我总是首先转向基类,然后转向T(直接转换为T不会为派生类编译)

class SomeGenericClass<T> where T:Foo
{
    private readonly SomeDelegate<T> _action = _ => Console.WriteLine("Foo");

    public void DoStuff()
    {
        _action((T)new Foo());
        _action((T)(Foo)new Boo());
    }
}

编辑

假设我将DoStuff更改为:

public void DoStuff(T foo)
{
    _action(foo);
}

测试:

var genericInstance = new SomeGenericClass<Foo>();
var foo = new Foo();
var boo = new Boo();
genericInstance.DoStuff(foo);
genericInstance.DoStuff(boo);

一切都很好;在DoStuff中直接添加这些实例有什么区别?

public void DoStuff(T foo)
{
    _action(foo);
    _action(new Foo()); //does not compile
}

编辑

关于@Rawling的答案和评论:

添加一个不继承自Foo的类Moo => class Moo{},关于我的工作可能会导致运行时异常的事实:

public void DoStuff(T foo)
{
    _action(foo);
    _action((T)new Foo());
    _action((T)(Foo)new Boo());
    _action((T)(Foo)new Moo()); //this does not even compile
}
答案

T可能是一种来自Foo的类型,在这种情况下,将new Foo()传递给SomeDelegate<T>是不安全的。代表可能会尝试访问T上不存在的Foo成员。

你的第一个解决方法有效,但你可能会发现你的代表在解决方法之前无法做到所有事情,因为它现在需要一个Foo,而不是T

您的第二个解决方法可能会导致运行时异常。

以上是关于无法将X类型转换为T.泛型类中的泛型委托的主要内容,如果未能解决你的问题,请参考以下文章

17.scala的泛型类

将泛型值推送到 Typescript 中泛型类中的泛型列表

在 Typescript 的泛型类中初始化泛型类型

JAVA中的泛型类是啥东西?

泛型类的基本使用

受保护的泛型类 - 是不是支持?