首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在C#中转换drops实现的成员数组

在C#中转换drops实现的成员数组
EN

Stack Overflow用户
提问于 2015-03-18 17:19:00
回答 2查看 87关注 0票数 1

考虑:

代码语言:javascript
复制
class Order
{
    public List<OrderItem> OrderItems {get;set;}
}

class SalesOrder : Order
{
    public List<SalesOrderItem> OrderItems {get;set;}
}

class OrderItem {}

class SalesOrderItem : OrderItem {}

当试图施展

代码语言:javascript
复制
SalesOrder salesorder = new SalesOrder();
salesorder.OrderItems = List<SalesOrderItem>();
salesorder.OrderItems.Add(new SalesOrderItem());
Order order = salesorder;

order.Orderitems为空。有什么方法可以让这个转换使用派生属性吗?

我已经尝试过与接口进行协变,但之后不能使用List,而且使用IEnumerable将不允许公共设置器。对如何做到这一点有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-03-18 17:46:38

代码中有几个错误。看起来您混淆了一些面向对象的概念,以及它们在C#中的实现方式。

在您的代码中,您正在尝试从SalesOrder派生Order。这是最重要的错误:它违反了Liskov代换原理。特别是,它意味着派生类不能为其成员的签名添加额外的约束。请注意,您的SalesOrder类确实添加了这样的约束:订单项必须是SalesOrderItem类型,而Order类则接受从OrderItem派生的所有订单项。

相反,您需要的是专门化:SalesOrder类比Order类更严格:它只能包含SalesOrderItems。专业化是通过使用泛型来实现的。因此,您可以按照以下方式定义您的类:

代码语言:javascript
复制
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
{
}

Update:为了说明为什么不可能将SalesOrder转换为Order<OrderItem>,请考虑以下静态方法:

代码语言:javascript
复制
public static void AddOrderItem(Order<OrderItem> order)
{
    var item = new OrderItem();
    order.OrderItems.Add(order);
}

如果SalesOrder是从Order<OrderItem>派生的,则可以编写以下内容:

代码语言:javascript
复制
var order = new SalesOrder();
AddOrderItem(order);

但是,这将导致类型错误,因为SalesOrder不能包含普通的OrderItem。现在,如果将SalesOrder转换为Order的唯一原因是读取命令项,则可以引入一个接口:

代码语言:javascript
复制
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并读取订单项。

票数 3
EN

Stack Overflow用户

发布于 2015-03-18 17:42:56

这就是所谓的"影影“。

您的salesOrder有两个OrderItems属性-一个是只对SalesOrder可见的,另一个是只能对Orders可见的。子类中的OrderItems属性隐藏在父类中。您正在向一个项目中添加一个项,然后观察另一个项。

我认为您需要重新考虑您的设计,但是可以通过从子类中删除属性来解决这个问题:

代码语言:javascript
复制
class Order
{
    public Order()
    {
        OrderItems = new List<OrderItem>();
    }
    public List<OrderItem> OrderItems {get;set;}
}

class SalesOrder : Order { }

class OrderItem {}

class SalesOrderItem : OrderItem {}

另一个选项是使Order成为一个泛型类:

代码语言:javascript
复制
class Order<T> where T: OrderItem
{
    public Order()
    {
        OrderItems = new List<T>();
    }
    public List<T> OrderItems {get;set;}
}

class SalesOrder : Order<SalesOrderItem> { }

class OrderItem {}

class SalesOrderItem : OrderItem {}
代码语言:javascript
复制
SalesOrder salesorder = new SalesOrder();
salesorder.OrderItems.Add(new SalesOrderItem());
Order<SalesOrderItem> order = salesorder;

第二种方法的好处是它允许OrderItems存储特定类型的订单项,而不是最普通的类型。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29128590

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档