我有两个班级:
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;
}
我想创建一个可以容纳这两者的List,但我不希望我的列表能够保存任何其他数据类型。怎么办呢?
答案 0 :(得分:58)
最简单的方法是声明一个接口,并让两种类型实现它:
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>();
答案 1 :(得分:34)
您已经得到了一些解释,说明如何使用空接口执行此操作:
interface IMachineSomething {}
…
var m = new List<IMachineSomething>();
如果您只想将对象放入该列表中,这样可以正常工作。但是如果你想从列表中实际获取对象呢?你真的可以用它们做什么,上面的解决方案会强迫你做什么?
以下显示您可以使用非空界面做得更好。
IMachineSomething
是一个空接口。也就是说,如果您确实想要对列表中的对象执行某些操作,那么您将要看到的只是该接口定义的空契约。所有实际功能都以具体的class
类型为基础。因此,您首先必须检查其类型,然后执行类型转换以访问公共字段:
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 …
}
由于您正在使用面向对象的语言,因此有一个更好的解决方案:多态性。也就是说,在界面中放置常用功能(属性和方法),这样当您浏览列表时就不需要区分类型了:
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 …)
类型检查和后续的类型转换,并将代码简化为:
foreach (IMachineSomething sth in m)
{
sth.DoSomething();
}
循环不再需要关心每个元素的处理方式。所有它需要知道它必须与元素“做某事”,元素本身将知道这意味着什么。
if
类型检查)。答案 2 :(得分:8)
您有两种方式:
1-使用继承:
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>();
我推荐你的继承......
答案 3 :(得分:7)
只需创建自己的界面
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()
};
答案 4 :(得分:5)
您可以使这两个类实现相同的接口,并使该接口成为List
的包含泛型类型。
答案 5 :(得分:2)
现在,使用C#7.0就像使用元组一样简单:
public List<(MachineLine line, MachineCircle circle)> machineList { get; set; }
添加数据(注意((和)),params的一个括号和另一个表示元组的括号:
MachineLine theLine = ...;
MachineCircle theCircle = ...;
machineList.Add((theLine, theCircle));
获取数据:
MachineLine ml = emailSender.ElementAt(3).line;
MachineCircle mc = emailSender.ElementAt(3).circle;
就像一,二,三一样简单!