在迭代对象列表时避免多个“if”语句c#

时间:2013-10-02 08:52:23

标签: c# oop object types casting

我有各种类生成excel图。

每个班级都会生成不同的图表。

它们共享相同的私有变量,具有不同的值。

我希望编写一个通用代码,以防止“if”语句确定它是哪个图形。

以下是其中一个类的示例:

using System;

namespace GraphsGenerator
{
   public class GraphOne
   {
       #region Private Members

       private string m_baseDir = "";
       private static string m_graphName = "GraphOne";
       private string m_imageFile = m_graphName + Utils.ImageExtension;

       #endregion Private Members

       #region Properties

       public string BaseDir
       {
           set { m_baseDir = value; }
       }
       public string GraphName
       {
           get { return m_graphName; }
       }
       public string ImageFile
       {
           get { return m_imageFile; }
           set { m_imageFile = value; }
       }

       #endregion Properties

       #region Constructor


       public HandTrackingGraphs(string baseDir)
       {
           m_baseDir = baseDir;
       }

       #endregion Constructor
   }
 }

我试图在我的主要内容中执行此操作:

List<object> listOfGraphs = new List<object>();
listOfGraphs.Add(new GraphOne());
listOfGraphs.Add(new GraphTwo());
listOfGraphs.Add(new GraphThree());

foreach (object currentGraph in listOfGraphs)
{
   string imageFile = currentGraph.ImageFile;
}

但当然不能这样做。

有什么想法吗?

5 个答案:

答案 0 :(得分:8)

  

它们共享相同的私有变量,具有不同的值。

它们都应该实现相同的接口,这会暴露ImageFile属性。例如:

public interface IGraph
{
    // TODO: Consider making this read-only in the interface...
    public string ImageFile { get; set; }
}

然后你可以:

List<IGraph> listOfGraphs = new List<IGraph>();
listOfGraphs.Add(new GraphOne());
listOfGraphs.Add(new GraphTwo());
listOfGraphs.Add(new GraphThree());

foreach (IGraph currentGraph in listOfGraphs)
{
   string imageFile = currentGraph.ImageFile;
}

您也可以使用抽象基类而不是接口。这有点限制性,但这意味着图表也可以共享通用实现。

(你甚至可以创建一个由抽象基类实现的接口,如果你真的想要灵活性而且还需要代码重用。)

答案 1 :(得分:4)

  

但当然不能这样做。

它可以使用接口。定义包含要运行的方法的接口:

public interface IGraphWithImageFile
{
    string ImageFile { get; }
}

然后将接口应用于所有类,并将列表声明为List<IGraphWithImageFile>

答案 2 :(得分:2)

使所有类继承自常见的GraphBase抽象类。将您的公共属性作为抽象放在此类上,然后在派生类中覆盖它们。

答案 3 :(得分:1)

已经建议了接口,所以为了给你另一种选择 - 你可以使用基类,因为你不仅可以共享公共属性/方法,还可以共享常见的实现,例如。

public abstract class Graph
{
   #region Private Members

   private string m_baseDir = "";
   private string m_imageFile = m_graphName + Utils.ImageExtension;

   #endregion Private Members

   #region Properties

   public string BaseDir
   {
       set { m_baseDir = value; }
   }
   public string GraphName
   {
       get { return m_graphName; }
   }

   public abstract string ImageFile { get; }

   #endregion Properties

   #region Constructor


   public HandTrackingGraphs(string baseDir)
   {
       m_baseDir = baseDir;
   }

   #endregion Constructor
}

public class GraphOne : Graph
{
    public override string ImageFile { get { return "GraphOne"; } }
}

public class GraphTwo : Graph
{
    public override string ImageFile { get { return "GraphTwo"; } }
}

public class GraphThree : Graph
{
    public override string ImageFile { get { return "GraphThree"; } }
}

然后您的用法变为

List<Graph> listOfGraphs = new List<Graph>();
listOfGraphs.Add(new GraphOne());
listOfGraphs.Add(new GraphTwo());
listOfGraphs.Add(new GraphThree());

foreach (IGraph currentGraph in listOfGraphs)
{
    string imageFile = currentGraph.ImageFile;
}

答案 4 :(得分:0)

在这种情况下,您只需要实施Strategy Pattern 要了解一下这段代码

abstract class AbsGraph
{
    public string ImageFile { get; protected set; }
    //other properties

    public abstract void DrawGraph();
    //other methods

    public void CommonMethod()
    { }
    //other common method
}

class Graph1 : AbsGraph
{
    public override void DrawGraph()
    {
        //do graph specific task
    }
}

class Graph2 : AbsGraph
{
    public override void DrawGraph()
    {
        //do graph specific task
    }
}

class Graph3 : AbsGraph
{
    public override void DrawGraph()
    {
        //do graph specific task
    }
}

现在你可以做到

var absGraphs = new List<AbsGraph>
                    {
                        new Graph1(),
                        new Graph2(),
                        new Graph3()
                    };
foreach (var graph in absGraphs)
{
    graph.DrawGraph();
}