C#一个列表中的不同类对象

时间:2012-12-03 16:15:47

标签: c# list generics interface polymorphism

我现在已经四处寻找解决这个问题的方法了。我找到了几种可以解决它的方法,但说实话,我没有意识到哪种方式被认为是“正确的”C#或OOP解决方法。我的目标不仅是解决问题,而且还要开发一套良好的代码标准,我很确定有一种标准的方法可以解决这个问题。

假设我有两种类型的打印机硬件及其各自的类和通信方式:PrinterType1,PrinterType2。

如果需要,我还希望以后能够添加另一种类型。抽象中的一步有很多共同之处。作为示例,应该可以将字符串发送到它们中的每一个。它们都有共同的变量,每个类都有唯一的变量。 (例如,通过COM端口进行通信并具有此类对象,而另一个通过TCP进行通信并具有此类对象)。

然而,我想实现所有这些打印机的列表,并能够通过列表并在所有打印机上执行“发送(字符串消息)”,而不管类型如何。我还想访问两个对象相同的“PrinterList [0] .Name”变量,但是我也想在某些地方访问特定于对象本身的数据(例如在设置窗口中)为一个对象设置COM端口名称的应用程序和另一个对象的IP /端口号。

所以,简而言之:

共同点:

  • 名称
  • 发送()

特定于PrinterType1:

  • 端口

特定于PrinterType2:

  • IP

例如,我希望对所有对象执行Send(),无论其类型和对象数量如何。

我已经阅读过关于多态,泛型,接口等的内容,但我想知道在我看来这个问题通常会在C#(和/或OOP)中处理。

我确实尝试过制作一个基类,但对我来说这似乎并不合适。例如,我没有在基类本身中使用“字符串发送(字符串消息)”函数。那么,为什么我会在派生类中定义一个需要被覆盖的东西,因为我从来没有在基类中使用过该函数?

我真的很感谢任何答案。这里的人似乎非常有见识,这个地方早就为我提供了许多解决方案。现在我终于有了一个帐户来回答并投票。

修改

另外解释一下,我还希望能够访问实际printertype的对象。例如,PrinterType1中的Port变量是一个SerialPort对象。我想访问它像: PrinterList[0].Port.Open()

并且可以访问底层端口的全部功能。同时我想调用对于不同对象以相同方式工作的泛型函数(但具有不同的实现):

foreach (printer in Printers)
    printer.Send(message)

5 个答案:

答案 0 :(得分:9)

使用接口的伪示例。

public interface IPrinter
{
   void Send();
   string Name { get; }
}

public class PrinterType1 : IPrinter
{
  public void Send() { /* send logic here */ }
  public string Name { get { return "PrinterType1"; } }
}

public class PrinterType2 : IPrinter
{
  public void Send() { /* send logic here */ }
  public string Name { get { return "Printertype2"; } }

  public string IP { get { return "10.1.1.1"; } }
}


// ...
// then to use it
var printers = new List<IPrinter>();

printers.Add(new PrinterType1());
printers.Add(new PrinterType2());

foreach(var p in printers)
{
  p.Send();

  var p2 = p as PrinterType2;

  if(p2 != null) // it's a PrinterType2... cast succeeded
    Console.WriteLine(p2.IP);
}

答案 1 :(得分:2)

创建一个包含“常用”方法的界面(比如说IPrinterType)并使用此界面。

答案 2 :(得分:2)

您正在寻找的是一个抽象基类,如下所示:

abstract class Printer
{
    public string Name { get; set; }
    public abstract string Send(string Message);
}

然后继承该类并根据需要实现Send()函数。

您也可以在此处使用界面。不同之处在于接口只能指定继承者必须实现的属性,方法和事件 - 它本身不实现任何代码。您使用哪种方法取决于哪种方式最适合您的应用。你最好同时做两件事(创建一个实现接口的抽象类)。

答案 3 :(得分:1)

对于&#34的特定问题;例如,我没有使用&#34;字符串发送(字符串消息)&#34;函数在基类本身。那么,为什么我会在派生类中定义一个需要被覆盖的东西,因为我从来没有在基类中使用过该函数?&#34;

确实没有必要在基类中实现它。

如果您的基类是一个抽象类,您可以简单地声明它,然后将其留给具体类来实现它。

如果您不想提供任何具体的实现,那么您可能会更好地使用所有具体类需要实现的接口,而不是抽象类。

答案 4 :(得分:0)

您所描述的几乎是所设计的接口。将所有常用属性/方法放入其中并隐藏具体实现。我仍然建议使用基类Printer类,因为显然会有类似的代码可以共享。

当涉及更明确的属性时,您提到例如端口/ IP,你必须知道你正在处理什么类型。此时,您可以将其转换为正确的类型。