创建基础 class 的集合,然后访问集合项中的派生 classes 的属性
Creating a collection of base class, then access properties of derived classes in the collection items
我有class这样的,
class Base
{
int Id { get; set; }
}
class Derived1 : Base
{
string DerivedProperty1 { get; set; }
}
class Derived2 : Base
{
string DerivedProperty2 { get; set; }
}
现在我有一个像这样的合集class
public class MyCollection
{
List<Base> items;
public void Add(Base baseItem)
{
// if baseItem is Derived1, if items contain an item of type Derived1 and has the same DerivedProperty1 value as baseItem, throw exception
// if baseItem is Derived2, if items contain an item of type Derived2 and has the same DerivedProperty2 value as baseItem, throw exception
items.Add(baseItem);
}
}
我不认为先检查 baseItem 的类型再进行转换是一个很好的做法,对吗?否则你建议我如何解决这个设计问题?
根据您的代码和注释,正确的方法是为 Base
提供一个 IsDuplicateOf
方法并在派生的 类 中覆盖它。像这样:
class Base
{
int Id { get; set; }
public virtual bool IsDuplicateOf(Base other)
{
return other != null && Id == other.Id;
}
}
class Derived1 : Base
{
string DerivedProperty1 { get; set; }
public override bool IsDuplicateOf(Base other)
{
return IsDuplicateOf(other as Derived1);
}
private bool IsDuplicateOf(Derived1 other)
{
return other != null && DerivedProperty1 == other.DerivedProperty1;
}
}
class Derived2 : Base
{
string DerivedProperty2 { get; set; }
public override bool IsDuplicateOf(Base other)
{
return IsDuplicateOf(other as Derived2);
}
private bool IsDuplicateOf(Derived2 other)
{
return other != null && DerivedProperty2 == other.DerivedProperty2;
}
}
您将在 Add
方法中使用该方法:
public void Add(Base baseItem)
{
if(items.Any(x => baseItem.IsDuplicateOf(x)))
throw new DuplicateItemException(...);
items.Add(baseItem);
}
但是请注意,如果列表中的项目很多并且 IsDuplicateOf
中的代码变得更加复杂,这种方法可能会变慢。
如果不首先转换为派生的 class,则无法从基础 class 访问派生的 class 属性。但是,在你的情况下,你可以做一些不同的事情 - 而不是你当前的 Add
方法,它需要一个 Base
实例作为参数,创建几个 Add
方法重载,一个用于每个派生 class:
public void Add(Derived1 item)
{
if(items.OfType<Derived1>().Any(i => i.DerivedProperty1 == item.DerivedProperty1)
throw new InvalidOperationException("An item with the same DerivedProperty1 already exist");
items.Add(baseItem);
}
public void Add(Derived2 item)
{
if(items.OfType<Derived2>().Any(i => i.DerivedProperty2 == item.DerivedProperty2)
throw new InvalidOperationException("An item with the same DerivedProperty2 already exist");
items.Add(baseItem);
}
我有class这样的,
class Base
{
int Id { get; set; }
}
class Derived1 : Base
{
string DerivedProperty1 { get; set; }
}
class Derived2 : Base
{
string DerivedProperty2 { get; set; }
}
现在我有一个像这样的合集class
public class MyCollection
{
List<Base> items;
public void Add(Base baseItem)
{
// if baseItem is Derived1, if items contain an item of type Derived1 and has the same DerivedProperty1 value as baseItem, throw exception
// if baseItem is Derived2, if items contain an item of type Derived2 and has the same DerivedProperty2 value as baseItem, throw exception
items.Add(baseItem);
}
}
我不认为先检查 baseItem 的类型再进行转换是一个很好的做法,对吗?否则你建议我如何解决这个设计问题?
根据您的代码和注释,正确的方法是为 Base
提供一个 IsDuplicateOf
方法并在派生的 类 中覆盖它。像这样:
class Base
{
int Id { get; set; }
public virtual bool IsDuplicateOf(Base other)
{
return other != null && Id == other.Id;
}
}
class Derived1 : Base
{
string DerivedProperty1 { get; set; }
public override bool IsDuplicateOf(Base other)
{
return IsDuplicateOf(other as Derived1);
}
private bool IsDuplicateOf(Derived1 other)
{
return other != null && DerivedProperty1 == other.DerivedProperty1;
}
}
class Derived2 : Base
{
string DerivedProperty2 { get; set; }
public override bool IsDuplicateOf(Base other)
{
return IsDuplicateOf(other as Derived2);
}
private bool IsDuplicateOf(Derived2 other)
{
return other != null && DerivedProperty2 == other.DerivedProperty2;
}
}
您将在 Add
方法中使用该方法:
public void Add(Base baseItem)
{
if(items.Any(x => baseItem.IsDuplicateOf(x)))
throw new DuplicateItemException(...);
items.Add(baseItem);
}
但是请注意,如果列表中的项目很多并且 IsDuplicateOf
中的代码变得更加复杂,这种方法可能会变慢。
如果不首先转换为派生的 class,则无法从基础 class 访问派生的 class 属性。但是,在你的情况下,你可以做一些不同的事情 - 而不是你当前的 Add
方法,它需要一个 Base
实例作为参数,创建几个 Add
方法重载,一个用于每个派生 class:
public void Add(Derived1 item)
{
if(items.OfType<Derived1>().Any(i => i.DerivedProperty1 == item.DerivedProperty1)
throw new InvalidOperationException("An item with the same DerivedProperty1 already exist");
items.Add(baseItem);
}
public void Add(Derived2 item)
{
if(items.OfType<Derived2>().Any(i => i.DerivedProperty2 == item.DerivedProperty2)
throw new InvalidOperationException("An item with the same DerivedProperty2 already exist");
items.Add(baseItem);
}