C#没有隐式转换为继承的类型 [英] C# No implicit conversion to inherited type
问题描述
我希望有人可以向我解释这一点,因为我对此感到困惑.我的类和接口之间有一系列继承,并且带有一个工厂来实例化正确的对象.但是,我得到了一个 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
}
从我所见,ConnA
是Conn<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屋!