我要做的是使用单个调用返回基类的2个扩展的集合。这就是我所拥有的:
public interface IView
{
int Id { get; set; }
}
然后我有一个实现此接口的域模型
public class View: IView
{
public int Id { get; set; }
}
然后我有几个继承自基类的类
public class ViewA: View
{
public string PropertyA { get; set; }
}
和
public class ViewB: View
{
public string PropertyB { get; set; }
}
从这里我有一个列表,我试图包含两者:
var views = new List<IView>();
并从我的基础创建一个视图,因为ViewA和ViewB都有ID
var view = new View();
view.Id = 1;
现在我正在尝试将其转换为ViewA,所以我可以这样设置PropertyA:
var viewA = (ViewA)view;
但是调试器告诉我我无法将“视图”转换为ViewA(编译得很好)。
Unable to cast object of type 'View' to type 'ViewA'
我确信我对界面的理解缺少了一些东西 - &gt;基类继承但我认为你可以通过这种方式将“较小”类强制转换为“更多定义”类。阅读关于协方差,逆变和赋值兼容性,我认为我应该能够做到这一点;显然不是..
我想要做的是返回两种类型的视图的集合(因此列表),以便我可以在需要时将它们转换为更定义的视图,并在我只需要公共属性时将它们保留为基本视图
我宁愿在ViewA和ViewB中没有重复的属性,我正在尝试做什么,或者我只是把这一切都弄错了?
答案 0 :(得分:3)
我确信我对界面的理解缺少了一些东西 - &gt;基类继承但我认为你可以通过这种方式将“较小”类强制转换为“更多定义”类。阅读关于协方差,逆变和赋值兼容性,我认为我应该能够做到这一点;显然不是..
你已经倒退了(我想)。您始终可以将派生类型的实例强制转换为基本类型,但不能反过来。如果将实例强制转换为派生类型,则它必须是运行时该类型的实例。
看起来你要做的就是以某种方式从ViewA
的实例创建View
的实例。这不是铸造工作的方式。
以下是 工作可能有用的示例。如果您有自己的观点列表:
var views = new List<IView>();
然后添加ViewA
的实例:
views.Add(new ViewA());
现在,编译器“不知道”views[0]
是ViewA
- 毕竟它是IView
的列表。在这种情况下,您知道的不仅仅是编译器,而且演员阵容是合适的:
var viewA = (ViewA)views[0];
你还提到:
我宁愿在ViewA和ViewB中没有重复的属性
除非我遗漏了什么,否则你没有复制任何属性。 ViewA
和ViewB
具有不同的属性,并从Id
类继承View
属性。
换句话说,这很好看:
var view = new ViewA();
view.Id = 4;
答案 1 :(得分:1)
将ViewA
和ViewB
的实例添加到列表中,而不仅仅是View
:
var views = new List<IView>();
var view = new ViewA(); // add an instance of viewA
views.Add(view);
您可以直接访问项目(无需转换,感谢Andrew)更改基类的“Id”属性,因为该属性也在界面中定义:
var view = (View)views[0];
view.Id = 999;
或测试类型以访问其他更具体的属性:
var viewB = views[0] as ViewB; // first element is a ViewA, so viewB is null
if (viewB != null)
{
viewB.PropertyB = "someValue"; // doesn't run because viewB is null
}
var viewA = views[0] as ViewA;
if (viewA != null)
{
viewA.PropertyA = "someOtherValue"; // runs - you have an instance of viewA
}
答案 2 :(得分:0)
不,你不能将“较小”类强制转换为“更明确”的类。 但是您可以将viewA和viewB转换为View列表,以便在获取公共属性时使用。
答案 3 :(得分:0)
用于创建对象的类型是它应该始终的类型 - 它永远不会改变。
因此,您要将您的实例创建为:
var view = new View();
因为它继承了IView
,您可以将其引用为View
,但它永远不会改变View
的类型。
因此,当您尝试将其强制转换为ViewA
时,它会失败。它永远不会是ViewA
,除非你这样创建它。
所以,如果你这样做:
var view = new ViewA();
然后可以将其引用为IView
,View
或ViewA
,但它始终为ViewA
类型。