我有一个ClassAAA,它包含两个属性:
ClassAAA
{
public string PropertyX {get;set;}
public string PropertyY {get;set;}
}
还有一个单独的ClassBBB,它具有相同的属性和一个附加的属性:
ClassBBB
{
public string PropertyX {get;set;}
public string PropertyY {get;set;}
public string PropertyZ {get;set;}
}
比方说,我都正确初始化了两者,并假设其中有项目:
var aaa = new List<ClassAAA>;
...
var bbb = new List<ClassBBB>;
...
在两个列表上,我必须执行相同的逻辑,例如:
List<ClassAAA> Manipulate(List<ClassAAA> list)
{
return list.Where(l => PropertyX == ...).ToList();
}
List<ClassBBB> Manipulate(List<ClassBBB> list)
{
return list.Where(l => PropertyX == ...).ToList();
}
这两个Manipulate
方法的代码是相同的,但由于它们基于不同的对象,因此我不得不重复它们。
问题是:在这种情况下,如何避免逻辑重复?理想情况下,将有一种Manipulate
方法同时适用于两种类型的列表,但是如何?
PS-还假设我想避免使用反射。
编辑
谢谢大家,缺少的链接实际上是使用IEnumerable
,这是一个可行的解决方案:
class Program
{
static void Main(string[] args)
{
var aaa = new List<ClassAAA>();
aaa = Manipulate(aaa).Cast<ClassAAA>().ToList();
}
public static IEnumerable<IHaveProperties> Manipulate(IEnumerable<IHaveProperties> list)
{
return list;
}
}
public interface IHaveProperties
{
string PropertyX { get; set; }
string PropertyY { get; set; }
}
public class ClassAAA : IHaveProperties
{
public string PropertyX { get; set; }
public string PropertyY { get; set; }
}
public class ClassBBB : IHaveProperties
{
public string PropertyX { get; set; }
public string PropertyY { get; set; }
public string PropertyZ { get; set; }
}
它也可以在没有接口的情况下工作,并允许ClassBBB从ClassAAA继承。
答案 0 :(得分:2)
1-定义一个接口并使用您的类实现它:
public interface IHaveProperties
{
string PropertyX { get; set; }
string PropertyY { get; set; }
}
public class ClassAAA: IHaveProperties
{
public string PropertyX { get; set; }
public string PropertyY { get; set; }
}
public class ClassBBB : IHaveProperties
{
public string PropertyX { get; set; }
public string PropertyY { get; set; }
public string PropertyZ {get;set;}
}
2-定义操作方法:
IEnumerable<IHaveProperties> Manipulate(IEnumerable<IHaveProperties> list)
{
return list;
}
注意!,您应该在此处使用IEnumerable,而不是List,因为IEnumerable是协变的,因此它将允许您接受集合内的派生类型值。
3-像这样使用它:
Manipulate(new List<ClassAAA>());
有关其他信息,请阅读有关Covariance and Contravariance in Generics
答案 1 :(得分:1)
两个选项:如果ClassBBB
是对ClassAAA
的扩展,则让ClassBBB
从ClassAAA
继承:
class ClassAAA
{
public string PropertyX {get;set;}
public string PropertyY {get;set;}
}
class ClassBBB : ClassAAA
{
public string PropertyZ {get;set;}
}
然后只需定义一个Manipulate
对象即可使用IEnumerable<ClassAAA>
个对象:
List<ClassAAA> Manipulate(IEnumerable<ClassAAA> list)
{
return list.Where(l => PropertyX == ...).ToList();
}
IEnumerable
是使用out T
定义的,而不是仅使用T
定义的,这允许协方差,即泛型参数可以是子类。
由于ClassBBB
继承自ClassAAA
,因此您可以对两者使用相同的方法。这将编译:
var newList = Manipulate(new List<ClassBBB>());
如果ClassAAA
和ClassBBB
非常不同,则让它们实现一个接口:
interface IAnInterface
{
string PropertyX {get;set;}
string PropertyY {get;set;}
}
class ClassAAA : IAnInterface
{
public string PropertyX {get;set;}
public string PropertyY {get;set;}
}
class ClassBBB : IAnInterface
{
public string PropertyX {get;set;}
public string PropertyY {get;set;}
public string PropertyZ {get;set;}
}
然后定义一个通用的Manipulate
方法:
List<T> Manipulate(List<T> list) where T : IAnInterface
{
return list.Where(l => PropertyX == ...).ToList();
}
并使用如下:
var newList = Manipulate(new List<ClassBBB>());