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