多种数据类型的列表?

时间:2010-12-03 07:23:54

标签: c# class list

我有两个班级:

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,但我不希望我的列表能够保存任何其他数据类型。怎么办呢?

6 个答案:

答案 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();
}

循环不再需要关心每个元素的处理方式。所有它需要知道它必须与元素“做某事”,元素本身将知道这意味着什么。

另见:

答案 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;

就像一,二,三一样简单!