oɔɯ*_*ɯǝɹ 9 .net c# properties new-operator
考虑以下示例代码:
// delivery strategies
public abstract class DeliveryStrategy { ... }
public class ParcelDelivery : DeliveryStrategy { ... }
public class ShippingContainer : DeliveryStrategy { ... }
Run Code Online (Sandbox Code Playgroud)
和以下示例Order类:
// order (base) class
public abstract class Order
{
private DeliveryStrategy delivery;
protected Order(DeliveryStrategy delivery)
{
this.delivery = delivery;
}
public DeliveryStrategy Delivery
{
get { return delivery; }
protected set { delivery = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
当我派生出一种新类型的订单类时,它将继承DeliveryStrategy类型的Delivery属性.
现在,当给出CustomerOrders必须使用ParcelDelivery策略交付时,我们可以考虑在CustomerOrder类中" 新 "交付属性:
public class CustomerOrder : Order
{
public CustomerOrder()
: base(new ParcelDelivery())
{ }
// 'new' Delivery property
public new ParcelDelivery Delivery
{
get { return base.Delivery as ParcelDelivery; }
set { base.Delivery = value; }
}
}
Run Code Online (Sandbox Code Playgroud)
(CustomerOrder显然需要确保与Order兼容(polymorph))
这允许在CustomerOrder上直接使用ParcelDelivery策略,而无需进行强制转换.
你会考虑使用这种模式吗?为什么/为什么不呢?
更新:我提出了这种模式,而不是使用泛型,因为我想将它用于多个属性.我不想对所有这些属性使用泛型类型参数
Jon*_*eet 11
我更喜欢使类型通用:
public abstract class Order<TDelivery> where TDelivery : Delivery
{
public TDelivery Delivery { ... }
...
}
public class CustomerOrder : Order<ParcelDelivery>
{
...
}
Run Code Online (Sandbox Code Playgroud)
这确保了编译时的类型安全性,而不是将其留待执行时间.它还可以防止以下情况:
CustomerOrder customerOrder = new CustomerOrder();
Order order = customerOrder;
order.Delivery = new NonParcelDelivery(); // Succeeds!
ParcelDelivery delivery = customerOrder.Delivery; // Returns null
Run Code Online (Sandbox Code Playgroud)
哎哟.
我认为new通常是最后的手段.它在实现和使用方面引入了额外的复杂性.
如果您不想沿着通用路线走下去,我会介绍一个真正的新房产(名称不同).
我认为这是一个很好的模式.通过消除转换结果的需要,它可以更容易地显式使用派生类型,并且它不会"破坏"基类行为.实际上,在BCL的某些类中使用了类似的模式,例如查看DbConnection类层次结构:
因此,如果您通过DbConnection变量操作连接对象,CreateCommand将返回DbCommand; 如果你通过SqlConnection变量操作它,CreateCommand将返回一个SqlCommand,如果你将它分配给一个SqlCommand变量,则避免强制转换.
你可以使用泛型.
// order (base) class
public abstract class Order<TDeliveryStrategy> where TDeliveryStrategy : DeliveryStrategy
{
private TDeliveryStrategy delivery;
protected Order(TDeliveryStrategy delivery)
{
this.delivery = delivery;
}
public TDeliveryStrategy Delivery
{
get { return delivery; }
protected set { delivery = value; }
}
}
public class CustomerOrder : Order<ParcelDelivery>
{
public CustomerOrder()
: base(new ParcelDelivery())
{ }
}
Run Code Online (Sandbox Code Playgroud)