我有两个课程:
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;
}
Run Code Online (Sandbox Code Playgroud)
我想创建一个可以容纳这两个的List,但我不希望我的列表能够保存任何其他数据类型.如何才能做到这一点?
Dea*_*alk 60
最简单的方法是声明一个接口,并让两种类型实现它:
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;
}
Run Code Online (Sandbox Code Playgroud)
然后你可以这样做:
List<IMachine> m = new List<IMachine>();
Run Code Online (Sandbox Code Playgroud)
sta*_*ica 37
您已经得到了一些解释,说明如何使用空接口执行此操作:
interface IMachineSomething {}
…
var m = new List<IMachineSomething>();
Run Code Online (Sandbox Code Playgroud)
如果您只想将对象放入该列表中,这可以正常工作.但是如果你想从列表中实际获取对象呢?你真的可以用它们做什么,上面的解决方案会强迫你做什么?
以下显示使用非空接口可以做得更好.
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 …
}
Run Code Online (Sandbox Code Playgroud)
由于您正在使用面向对象的语言,因此有一个更好的解决方案:多态性.也就是说,在界面中放置常用功能(属性和方法),这样您在浏览列表时就无需区分类型:
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
}
Run Code Online (Sandbox Code Playgroud)
这允许您摆脱if (sth is …)
类型检查和后续的类型转换,并简化您的代码:
foreach (IMachineSomething sth in m)
{
sth.DoSomething();
}
Run Code Online (Sandbox Code Playgroud)
循环不再需要关心每个元素的处理方式.所有它需要知道它必须与元素"做某事",元素本身将知道这意味着什么.
if
多态替换类型检查).Bet*_*moo 10
你有两种方式:
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>();
Run Code Online (Sandbox Code Playgroud)
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>();
Run Code Online (Sandbox Code Playgroud)
我推荐你的继承......
只需创建自己的界面
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()
};
Run Code Online (Sandbox Code Playgroud)
现在,使用 C# 7.0 就像使用元组一样简单:
public List<(MachineLine line, MachineCircle circle)> machineList { get; set; }
Run Code Online (Sandbox Code Playgroud)
要添加数据(注意 (( 和 )),参数的一个括号和另一个表示元组的括号):
MachineLine theLine = ...;
MachineCircle theCircle = ...;
machineList.Add((theLine, theCircle));
Run Code Online (Sandbox Code Playgroud)
获取数据:
MachineLine ml = emailSender.ElementAt(3).line;
MachineCircle mc = emailSender.ElementAt(3).circle;
Run Code Online (Sandbox Code Playgroud)
就像一,二,三一样简单!