【问题标题】:Avoiding multiple "if" statements when iterating a list of objects c#迭代对象列表时避免多个“if”语句c#
【发布时间】:2013-10-08 14:51:31
【问题描述】:

我有各种生成 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;
}

但这当然是做不到的。

有什么想法吗?

【问题讨论】:

    标签: c# oop object types casting


    【解决方案1】:

    在这种情况下,您只需要实现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();
    }
    

    【讨论】:

      【解决方案2】:

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

      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;
      }
      

      【讨论】:

        【解决方案3】:

        但这当然是做不到的。

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

        public interface IGraphWithImageFile
        {
            string ImageFile { get; }
        }
        

        然后将该接口应用于所有类,并将列表声明为List&lt;IGraphWithImageFile&gt;

        【讨论】:

          【解决方案4】:

          让所有的类都继承自一个通用的 GraphBase 抽象类。将您的公共属性作为抽象放在此类上,然后在派生类中覆盖它们。

          【讨论】:

            【解决方案5】:

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

            它们都应该实现相同的接口,该接口公开了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;
            }
            

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

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-02-09
              • 1970-01-01
              • 2016-07-24
              • 2017-03-11
              • 2020-06-19
              • 1970-01-01
              • 2016-02-19
              • 1970-01-01
              相关资源
              最近更新 更多