考虑:
class Order
{
public List<OrderItem> OrderItems {get;set;}
}
class SalesOrder : Order
{
public List<SalesOrderItem> OrderItems {get;set;}
}
class OrderItem {}
class SalesOrderItem : OrderItem {}
尝试投射时
SalesOrder salesorder = new SalesOrder();
salesorder.OrderItems = List<SalesOrderItem>();
salesorder.OrderItems.Add(new SalesOrderItem());
Order order = salesorder;
order.Orderitems
为空。我有什么办法可以将此转换与派生属性一起使用?我已经尝试过使用接口进行协方差,但是随后无法使用
List
,并且使用IEnumerable
将不允许使用公共设置器。关于如何实现这一目标的任何想法? 最佳答案
您的代码中有几个错误。看起来您在混淆一些OO概念及其在C#中的实现方式。
在您的代码中,您尝试从SalesOrder
派生Order
。这是最重要的错误:它违反了Liskov substitution principle。特别是,这意味着派生类不得在其成员的签名中添加其他约束。请注意,您的SalesOrder
类确实添加了这样的约束:订单项必须为SalesOrderItem
类型,而Order
类接受所有从OrderItem
派生的订单项。
相反,您想要的是专业化:SalesOrder
类比Order
类更严格:它只能包含SalesOrderItems。通过使用泛型来实现专业化。因此,您可以按以下方式定义类:
public class Order<T> where T: OrderItem
{
public List<T> OrderItems { get; set; }
}
public class OrderItem
{
}
public class SalesOrder : Order<SalesOrderItem>
{
}
public class SalesOrderItem : OrderItem
{
}
更新:为了说明为什么无法将
SalesOrder
强制转换为Order<OrderItem>
的方法,请考虑以下静态方法:public static void AddOrderItem(Order<OrderItem> order)
{
var item = new OrderItem();
order.OrderItems.Add(order);
}
如果
SalesOrder
源自Order<OrderItem>
,则可以编写以下代码:var order = new SalesOrder();
AddOrderItem(order);
但是,这将导致类型错误,因为SalesOrder不能包含普通的OrderItem。现在,如果将
SalesOrder
转换为Order
的唯一原因是阅读订单项,则可以引入一个接口:public interface IOrder
{
IEnumerable<OrderItem> GetItems();
}
public class Order<T> : IOrder where T: OrderItem
{
public List<T> OrderItems { get; set; }
public IEnumerable<OrderItem> GetItems()
{
return this.OrderItems;
}
}
现在,您可以将
SalesOrder
对象转换为IOrder
并阅读订单项。关于c# - 在C#中转换掉落已实现成员数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29128590/