c# - 通用对象需要强制转换,即使它实现了所需的接口(interface)

标签 c# .net generics interface

不要以为标题可以解释我在说什么,而且解释起来有点困难,所以我让代码来说话。您可以将其复制并粘贴到 LINQPad 中并将其作为 C# 程序运行,或者在 Visual Studio 中作为常规 C# 项目进行必要的调整(例如:将对 Dump() 的调用更改为 Console.Writeline() 等)-

请注意,如果您取消注释 doStuff 方法中的行,它将无法编译。

我的问题是,当 generic2 已经实现 Iab<TA,TB> 时,为什么我还需要强制转换? ?这是某种协方差吗?我仍在使用 .NET 3.5。

void Main()
{
    doStuff<a,b>();
}

public void doStuff<TA, TB>()
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    Iab<TA, TB> x = null;

    x = new generic1<TA, TB>();
    x.Go().Dump();

    //x = new generic2<TA>(); // <-Cannot implicitly convert type 'UserQuery.generic2<TA>' to 'UserQuery.Iab<TA,TB>'. An explicit conversion exists (are you missing a cast?)
    x = (Iab<TA, TB>) new generic2<TA>();
    x.Go().Dump();
}

public interface Ia
{}

public interface Ib
{}

public class a : Ia
{}

public class b : Ib
{}

public interface Iab<TA,TB>
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    string Go();
}

public class generic1<TA, TB> : Iab<TA,TB>
where TA : class, Ia, new()
where TB : class, Ib, new()
{
    public string Go()
    {
        return "generic Base called";
    }
}

public class generic2<TA> : Iab<TA,b>
where TA : class, Ia, new()
{
public string Go()
    {
        return "generic Sub called";
    }
}

最佳答案

我相信这是因为当一种或多种类型(在本例中为 TS)在编译时未知时,您总是会遇到该错误。

编译器无法保证 doStuff() 会以兼容的类型被调用,因此它会强制您进行转换。

要了解为什么编译器不能这样做,请尝试按如下方式调用 doStuff():

public class X: b {}

...

doStuff<a, X>(); // Compiles ok but:

Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'generic21[Demo.Program+X]' to type 'Iab2[Demo.Program+X,Demo.Program+Y]'.

因此您可能会使用会使其崩溃的类型来调用它;编译器不会默默地让你这样做。

关于c# - 通用对象需要强制转换,即使它实现了所需的接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16768604/

相关文章:

c# - 如何确定程序集名称是否与请求的部分程序集名称匹配

c# - 如何在 C# 的 JsonNet 中 DeserializeObject 时设置类属性

c# DatagridView 控件(VirtualMode)和线程

c# - 为什么未检测到使用继承类型的泛型类的类约束?

C# 泛型和转换问题

c# - Nullable<T> 混淆

c# - ValidationMessageFor 与 AddModelError(key, message) 一起。关键是什么?

c# - 如何从 C# 代码运行 VBS 脚本

c# - 如何在我的 Compact Framework 应用程序中使用 OpenStreetMap?

c# - 如何使用 Linq 在字符串中搜索列表的任何项目