多种数据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都与具体的class
types有关。 所以你首先必须检查他们的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(); }
循环不再需要关心每个元素如何被精确处理。 所有它需要知道它必须“做某事”与一个元素,并且元素本身将知道这意味着什么。
也可以看看:
- 条件和多态 (演示)讨论了这个答案的相同的主要思想(取代
if
types检查与多态性)。 - 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。