C#没有隐式转换为继承的类型 [英] C# No implicit conversion to inherited type

查看:144
本文介绍了C#没有隐式转换为继承的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望有人可以向我解释这一点,因为我对此感到困惑.我的类和接口之间有一系列继承,并且带有一个工厂来实例化正确的对象.但是,我得到了一个 Cannot不能将类型'Conn'隐式转换为IConn.存在显式转换(您是否缺少演员表?)

I'm hoping someone can explain this to me as I'm confused about it. I have a series of inheritance amongst my classes and interfaces, with a factory to instantiated the correct object. However, I am getting a Cannot implicitly convert type 'Conn' to IConn. An explicit conversion exists (are you missing a cast?)

这是该代码的精简版.

public abstract class Id
{
    public int Id { get; set; }
}

public abstract class Id_SourceId
{
    public int SourceId { get; set; }
}

public interface IConn<T> where T : Id
{
    IEnumerable<T> GetIds();
}

public abstract class Conn<T> : IConn<T> where T : Id_SourceId{ ... }

public class A_Id_SourceId : Id_SourceId{ ... }
public class B_Id_SourceId : Id_SourceId{ ... }

public class ConnA : Conn<A_Id_SourceId > { ... }
public class ConnB : Conn<B_Id_SourceId > { ... }

public IConn<Id_SourceId> Create(bool val)
{
    if (val)
        return new ConnA(); //<-- Error here
    else
        return new ConnB(); //<-- And here
}

从我所见,ConnAConn<A_Id_SourceId>类型,而(进行数学类型替换)又是IConn<A_Id_SourceId>类型,再次是IConn<Id_SourceId>类型.

From what I can see ConnA is of type Conn<A_Id_SourceId> which in turn (doing a maths type substitution) is of type IConn<A_Id_SourceId> and again, is of type IConn<Id_SourceId>.

我意识到显式强制转换(return (IConn<Id_SourceId>)(new ConnA()))可以解决它,但是我认为它相当丑陋,并且强制转换很慢(据我了解).但我也想了解为什么它不起作用.

I realise an explicit cast (return (IConn<Id_SourceId>)(new ConnA())) would resolve it, but I think its rather ugly, and the cast would be slow (from what I understand). But also I want to understand why it doesn't work.

谢谢.

推荐答案

默认情况下,通用参数不参与继承层次结构,因为这样做会破坏类型安全性,但是,由于您的IConn<T>接口仅返回对象的键入T,并且不需要它们作为参数,则可以使

Generic arguments, by default, do not participate in inheritance hierarchies, as doing so would break type safety, however, as your IConn<T> interface only returns objects of type T, and doesn't require them as arguments, you can make the interface covariant, by adding the out keyword:

public interface IConn<out T> : where T : Id
{
    IEnumerable<T> GetIds();
}

这样做,编译器对可以安全地使用更多派生的泛型类型感到满意:

By doing so, the compiler is satisfied that more derived generic types can safely be used:

public IConn<Id_SourceId> Create(bool val)
{
    if (val)
        return new ConnA(); //<-- Now fine
    else
        return new ConnB(); //<-- Also fine
}


如果您想知道为什么会发生这种情况,也许可以通过以下示例来阐明.


If your wondering why this is the case, maybe this example will clarify.

想象IConn<T>是不变的,并且有一个接受Id对象的方法:

Imagine IConn<T> was invariant, and had a method that accepted Id objects:

public interface IConn<T> : where T : Id
{
    IEnumerable<T> GetIds();
    void AddId(Id id);
}

Conn<T>的实现方式如下:

public class Conn<T> : IConn<T>
{
    private List<T> ids = new List<T>();
    public void AddId(T id) => ids.Add(id);
}

然后您使用ConnA代替了IConn<Id_SourceId>:

IConn<Id_SourceId> connA = new ConnA();

B_Id_SourceId sourceB = new B_Id_SourceId();

// B_Id_SourceId inherits from Id_SourceId

connA.AddId(sourceB); // Tries to add a `B_Id_SourceId` to a list of `A_Id_SourceId`!

这篇关于C#没有隐式转换为继承的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆