考虑:

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/

10-09 05:22