C# 关于向下投射的泛型继承澄清

C# 关于向下投射的泛型继承澄清,c#,generics,inheritance,C#,Generics,Inheritance,我有一个泛型接口层次结构,它描述了其他泛型类型的一些控制器,我很难在脑海中澄清为什么特定的强制转换场景是无效的 简化代码如下: // 'DTO' interfaces public interface IBase { } public interface IDerived : IBase { } // 'DTOs' public class Base : IBase { } public class Derived : Base, IDerived { } // controller

我有一个泛型接口层次结构,它描述了其他泛型类型的一些控制器,我很难在脑海中澄清为什么特定的强制转换场景是无效的

简化代码如下:

// 'DTO' interfaces
public interface IBase
{ }

public interface IDerived : IBase
{ }


// 'DTOs'
public class Base : IBase
{ }

public class Derived : Base, IDerived
{ }


// controller interfaces
public interface IBaseController<T> where T : class, IBase
{ }

public interface IDerivedController : IBaseController<IDerived>
{ }


// controllers
public class BaseController<T> : IBaseController<T>
    where T : class, IBase
{ }

public class DerivedController : BaseController<IDerived>, IDerivedController
{ }
//'DTO'接口
公共接口IBase
{ }
公共接口驱动:IBase
{ }
//“DTO”
公共类基:IBase
{ }
派生的公共类:Base,IDerived
{ }
//控制器接口
公共接口IBaseController,其中T:class,IBase
{ }
公共接口IDERIVED控制器:IBaseController
{ }
//控制器
公共类BaseController:IBaseController
其中T:class,IBase
{ }
公共类派生控制器:BaseController、IDerivedController
{ }
现在,我遇到的问题是:

IDerivedController x = new DerivedController();
bool is1 = x is IDerivedController;   // true
bool is2 = x is IBaseController<IDerived>; // true
bool is3 = x is IBaseController<IBase>; // false ???
IDerivedController x=new-DerivedController();
bool is1=x是IDerivedController;//真的
bool is2=x是IBaseController;//真的
bool is3=x是IBaseController;//假???

最后一行是我的困惑所在。控制器接口正确关联,“DTO”。但不是两者都在一起

想一想,如果你有一个形状集合,那意味着什么:
集合
与(is-a)
集合
相同吗?如果是这样的话,我们就可以把任何形状放入我们的三角形集合中。如果
Collection
是(is-a)
Collection
,那么我们可以在里面放一个
Square
(毕竟,它是一个形状的集合),并且只希望得到
三角形


对于您的
BaseController

也有类似的情况。想想如果您有一组形状,这意味着什么:一个
集合
与(is-a)
集合
相同吗?如果是这样的话,我们就可以把任何形状放入我们的三角形集合中。如果
Collection
是(is-a)
Collection
,那么我们可以在里面放一个
Square
(毕竟,它是一个形状的集合),并且只希望得到
三角形

类似的情况也适用于您的
BaseController

请参阅,以获取有关各种通用接口的信息,这是您所要求的核心。您必须声明
IBaseController
实际上可以用作
IBaseController
,以便将其用作
IBaseController

为此,考虑尝试使用<代码>列表<代码>作为<代码> IIST VS尝试使用<代码> iQueBuy < /C> >作为<代码> InEdabess < /代码>。

IEnumerable
转换是可以的,因为您可以毫无问题地将项目用作
对象
s,但是您不能将任何
对象
添加到
列表
,因为这样它将包含
字符串
以外的内容

如果将其更改为
公共接口IBaseController,其中T:class,IBase
,则
x是IBaseController
将变为
true
。如果编译器抱怨您不能将
t
设置为
out
参数,那么您就不能进行您希望进行的转换(除非您更改接口以使其兼容)。

有关变体通用接口的信息,请参见。您必须声明
IBaseController
实际上可以用作
IBaseController
,以便将其用作
IBaseController

为此,考虑尝试使用<代码>列表<代码>作为<代码> IIST VS尝试使用<代码> iQueBuy < /C> >作为<代码> InEdabess < /代码>。

IEnumerable
转换是可以的,因为您可以毫无问题地将项目用作
对象
s,但是您不能将任何
对象
添加到
列表
,因为这样它将包含
字符串
以外的内容


如果将其更改为
公共接口IBaseController,其中T:class,IBase
,则
x是IBaseController
将变为
true
。如果编译器抱怨您不能将
t
设置为
out
参数,那么您就不能执行您希望执行的转换(除非您更改接口使其兼容)。

这是因为
IBaseController
不兼容。您可以这样声明它,使其协变:

public interface IBaseController<out T> where T : class, IBase
{
}
public interface IBaseController<T> where T : class, IBase
{
    void DoSomething(T x);
}
public class Derived2 : Base
{ }


IDerivedController x = ...
IBaseController<IBase> y = x;
y.DoSomething(new Derived2()); // oops! Derived2 doesn't implement IDerived
IBaseController
中,方法签名将是:

void Something(IDerived x)
现在,如果
IBaseController
可分配给
IBaseController
,则可以执行以下操作:

public interface IBaseController<out T> where T : class, IBase
{
}
public interface IBaseController<T> where T : class, IBase
{
    void DoSomething(T x);
}
public class Derived2 : Base
{ }


IDerivedController x = ...
IBaseController<IBase> y = x;
y.DoSomething(new Derived2()); // oops! Derived2 doesn't implement IDerived
public类Derived2:Base
{ }
IDERIVED控制器x=。。。
IBaseController y=x;
y、 DoSomething(新派生的2());//哎呀!Derived2不实现iDrived

这是因为
IBaseController
不是。您可以这样声明它,使其协变:

public interface IBaseController<out T> where T : class, IBase
{
}
public interface IBaseController<T> where T : class, IBase
{
    void DoSomething(T x);
}
public class Derived2 : Base
{ }


IDerivedController x = ...
IBaseController<IBase> y = x;
y.DoSomething(new Derived2()); // oops! Derived2 doesn't implement IDerived
IBaseController
中,方法签名将是:

void Something(IDerived x)
现在,如果
IBaseController
可分配给
IBaseController
,则可以执行以下操作:

public interface IBaseController<out T> where T : class, IBase
{
}
public interface IBaseController<T> where T : class, IBase
{
    void DoSomething(T x);
}
public class Derived2 : Base
{ }


IDerivedController x = ...
IBaseController<IBase> y = x;
y.DoSomething(new Derived2()); // oops! Derived2 doesn't implement IDerived
public类Derived2:Base
{ }
IDERIVED控制器x=。。。
IBaseController y=x;
y、 DoSomething(新派生的2());//哎呀!Derived2不实现iDrived

Rightio,谢谢。那就清楚了!不幸的是,我不能让我的类型在这里协变,所以我必须找到另一种方法。谢谢好的,谢谢你。那就清楚了!不幸的是,我不能让我的类型在这里协变,所以我必须找到另一种方法。谢谢