c# - 在泛型 (Y) 方法中使用泛型 (X) 委托(delegate),其中 Y 扩展了一些基类。无法转换为基类

标签 c# class generics constraints

public abstract class SomeBaseClass {}

public class SomeSpecificClass: SomeBaseClass {
    public int propertyA;
    public string propertyB;
}

public delegate void Callback<T>(T data);


public class Foo {


    void MethodA <T> (Callback<T> theInstance) where T: SomeBaseClass {
        MethodB(theInstance);
    }

    void MethodB(Callback<SomeBaseClass> theInstance) {

    }

    void MethodC() {
        Callback<SomeSpecificClass> cb = (data) => {};
        MethodA(cb);
    }

    void MethodD <T> (T theInstance) where T: SomeBaseClass {
        MethodE(theInstance);
    }

    void MethodE (SomeBaseClass theInstance) {

    }
}

MethodA 中产生错误:

Argument 1: cannot convert from 'Callback<T>' to 'Callback<SomeBaseClass>' [Assembly-CSharp] Callback<T> theInstance

但是 MethodD 可以很好地将它的实例传递给 MethodE

为什么我不能通过通用 Callback<T> MethodA 中的实例到 Callback<SomeBaseClass> 类型的参数在 MethodB 中,当我指定 T 扩展 SomeBaseClass 的约束时

最佳答案

基本上,您不能这样做,因为它不安全。

假设我们有一个派生自 SomeBaseClass 的具体类:

public class SomeOtherSpecificClass {}

假设我们更改您的 MethodB到:

void MethodB(Callback<SomeBaseClass> theInstance)
{
    theInstance(new SomeOtherSpecificClass());
}

那应该可以编译,对吧?毕竟,你只是传递一个 SomeOtherSpecificClass进入Callback<SomeBaseClass> ,这应该没问题。

然后如果我调用 MethodA像这样:

Callback<SomeSpecificClass> callbcak = data => Console.WriteLine(data.propertyA);
MethodA(callback);

... 那么如果所有这些都被允许,我们将传递一个 SomeOtherSpecificClass进入一个期待 SomeSpecificClass 的代表.

你的 MethodDMethodE例子很好,因为MethodE只能使用 SomeBaseClass 的成员...但是一个Callback<SomeSpecificClass>真的需要 SomeSpecificClass , 所以你不能把它当作一个接受 SomebaseClass 的方法.

为了更简单地展示这一点:

// This is valid...
string text = "";
object obj = text;

// This isn't...
Action<string> stringAction = text => Console.WriteLine(text.Length);
Action<object> objectAction = stringAction;
// ... because it would allow this:
objectAction(new object());

关于c# - 在泛型 (Y) 方法中使用泛型 (X) 委托(delegate),其中 Y 扩展了一些基类。无法转换为基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45672857/

相关文章:

具有泛型和协变返回的 Java 并行继承层次结构

class - UML:《原始语》的含义

generics - 为什么某些表达式中的泛型类型在 F# 模式匹配中匹配为 obj?

c# - 获取连续的日期范围

c# - Pattern.Matches() 在 xamarin 中不起作用

java - 类加载器的异常行为

c++ - 类型未声明错误

Java泛型捕获错误 "? super capture#1 of ? super T"

c# - 什么是 .exp 文件和 .lib 文件,我如何在我的 C# 项目中使用它们?

C#加密解密IV题