多种数据types的列表?

我有两个class:

public class MachineLine { public double X1; public double Y1; public double X2; public double Y2; public double Thickness; } public class MachineCircle { public double CenterX; public double CenterY; public double Radius; } 

我想做一个列表,可以同时拥有这两个,但我不希望我的列表能够容纳任何其他数据types。 如何才能做到这一点?

最简单的方法是声明一个接口,并使用这两种types来实现它:

 public interface IMachine { … } public class MachineLine : IMachine { public double X1; public double Y1; public double X2; public double Y2; public double Thickness; } public class MachineCircle : IMachine { public double CenterX; public double CenterY; public double Radius; } 

那么你可以这样做:

 List<IMachine> m = new List<IMachine>(); 

你有一些答案解释如何用一个空的界面来做到这一点:

 interface IMachineSomething {} … var m = new List<IMachineSomething>(); 

这工作正常,如果你想把对象放入该列表。 但是如果你想实际列表中获取对象呢? 你可以用他们做些什么,以上的解决办法会迫使你做什么?

以下显示您可以使用非空的界面做得更好。

IMachineSomething是一个空的界面。 也就是说,如果你真的想要对列表中的对象进行操作,那么你所看到的就是这个接口定义的空的契约。 所有的实际function都与具体的classtypes有关。 所以你首先必须检查他们的types,然后执行一个types转换以访问公共字段:

 foreach (IMachineSomething sth in m) { if (sth is MachineLine) { var machineLine = (MachineLine)sth; machineLine.DoThis(); } else if (sth is MachineCircle) { var machineCircle = (MachineCircle)sth; machineCircle.DoThat(); } else … } 

由于您正在使用面向对象的语言,所以有一个更好的解决scheme:多态性。 也就是说,在界面中添加通用的function(属性和方法),这样当你浏览你的列表时就不需要区分这些types了。

 interface IMachineSomething { void DoSomething(); } class MachineLine : IMachineSomething { … public void DoSomething() { DoThis(); } // example for implicit implementation, or… } class MachineCircle : IMachineSomething { … void IMachineSomething.DoSomething() { DoThat(); } // …explicit implementation } 

它允许你摆脱if (sth is …)types检查和随后的types转换,并简化你的代码:

 foreach (IMachineSomething sth in m) { sth.DoSomething(); } 

循环不再需要关心每个元素如何被精确处理。 所有它需要知道它必须“做某事”与一个元素,并且元素本身将知道这意味着什么。

也可以看看:

  • 条件和多态 (演示)讨论了这个答案的相同的主要思想(取代iftypes检查与多态性)。
  • Martin Fowler: angular色界面 (文章) ,是为特定交互而devise的界面。

只需创build自己的界面

 public interface IMySillyInterface {} public class MachineLine : IMySillyInterface { public double X1; public double Y1; public double X2; public double Y2; public double Thickness; } public class MachineCircle : IMySillyInterface { public double CenterX; public double CenterY; public double Radius; } List<IMySillyInterface> list = new List<IMySillyInterface> { new MachineCircle(), new MachineLine() }; 

你有两种方法:

1-使用inheritance:

 public class MachineShape{} public class MachineLine :MachineShape { public double X1; public double Y1; public double X2; public double Y2; public double Thickness; } public class MachineCircle : MachineShape { public double CenterX; public double CenterY; public double Radius; } List<MachineShape> m = new List<MachineShape>(); 

2-使用界面:

 public interface IMachineShape{} public class MachineLine : IMachineShape { public double X1; public double Y1; public double X2; public double Y2; public double Thickness; } public class MachineCircle : IMachineShape { public double CenterX; public double CenterY; public double Radius; } List<IMachineShape> m = new List<IMachineShape>(); 

我build议你的情况inheritance…

你可以使这两个类实现相同的接口,并使该接口成为List的包含genericstypes。