title: Refactoring Code to avoid Type Casting
body: <p>I have following C# code in .Net 4.0.  It requires a type casting of IBusiness to IRetailBusiness.</p>
  
  <pre><code>//Type checking
  if (bus is IRetailBusiness)
  {
         //Type casting
         investmentReturns.Add(new RetailInvestmentReturn((IRetailBusiness)bus));
  }
  
  if (bus is IIntellectualRights)
  {
         investmentReturns.Add(new IntellectualRightsInvestmentReturn((IIntellectualRights)bus));
  }
  </code></pre>
  
  <p><strong><em>Business Scenario:</em></strong></p>
  
  <p>I am designing a software system for and Investment Holding Company. The company has Retail business and IntellectualRights business. BookShop and AudioCDShop are examples of Retail business. EngineDesignPatent and BenzolMedicinePatent are examples of IntellectualRights business. These two business types are totally unrelated.</p>
  
  <p>The investment company has a concept called <code>InvestmentReturn</code>  (But each individual business is totally ignorant about this concept). InvestmentReturn is the profit gained from each business and it is calulated using <code>ProfitElement</code>. For each “Business Type” (Retail, IntellectualRights ), the ProfitElement used is different.</p>
  
  <p><strong>QUESTION</strong></p>
  
  <p>How to refactor this class design to avoid this <code>type casting</code> and <code>type checking</code>?</p>
  
  <p><strong><em>Abstract Investment</em></strong></p>
  
  <pre><code>public abstract class InvestmentReturn
  {
      public double ProfitElement { get; set; }
      public IBusiness Business{ get;  set; }
  
      public abstract double GetInvestmentProfit();
  
      public double CalculateBaseProfit()
      {
         double profit = 0;
  
         if (ProfitElement &lt; 5)
         {
             profit = ProfitElement * 5 / 100;
         }
         else if (ProfitElement &lt; 20)
         {
             profit = ProfitElement * 7 / 100;
         }
         else
         {
             profit = ProfitElement * 10 / 100;
         }
  
         return profit;
      }
  }
  </code></pre>
  
  <p><strong><em>Extensions</em></strong></p>
  
  <pre><code>public class RetailInvestmentReturn : InvestmentReturn
  {
      public RetailInvestmentReturn(IRetailBusiness retail)
      {
          Business = retail;
      }
  
      public override  double GetInvestmentProfit()
      {
          //GrossRevenue is the ProfitElement for RetailBusiness
          ProfitElement = ((IRetailBusiness)Business).GrossRevenue;
          return base.CalculateBaseProfit();
      }  
  }
  
  public class IntellectualRightsInvestmentReturn : InvestmentReturn
  {
  
      public IntellectualRightsInvestmentReturn(IIntellectualRights intellectual)
      {
          Business = intellectual;
      }
  
      public override double GetInvestmentProfit()
      {
          //Royalty is the ProfitElement for IntellectualRights Business
          ProfitElement = ((IIntellectualRights)Business).Royalty;
          return base.CalculateBaseProfit();
      }
  }
  </code></pre>
  
  <p><strong><em>Client</em></strong></p>
  
  <pre><code>class Program
  {
  
      static void Main(string[] args)
      {
  
          #region MyBusines
  
          List&lt;IBusiness&gt; allMyProfitableBusiness = new List&lt;IBusiness&gt;();
  
          BookShop bookShop1 = new BookShop(75);
          AudioCDShop cd1Shop = new AudioCDShop(80);
          EngineDesignPatent enginePatent = new EngineDesignPatent(1200);
          BenzolMedicinePatent medicinePatent = new BenzolMedicinePatent(1450);
  
          allMyProfitableBusiness.Add(bookShop1);
          allMyProfitableBusiness.Add(cd1Shop);
          allMyProfitableBusiness.Add(enginePatent);
          allMyProfitableBusiness.Add(medicinePatent);
  
          #endregion
  
          List&lt;InvestmentReturn&gt; investmentReturns = new List&lt;InvestmentReturn&gt;();
  
          foreach (IBusiness bus in allMyProfitableBusiness)
          {
              //Type checking
              if (bus is IRetailBusiness)
              {
                  //Type casting
                  investmentReturns.Add(new RetailInvestmentReturn((IRetailBusiness)bus));
              }
  
              if (bus is IIntellectualRights)
              {
                  investmentReturns.Add(new IntellectualRightsInvestmentReturn((IIntellectualRights)bus));
              }
          }
  
          double totalProfit = 0;
          foreach (var profitelement in investmentReturns)
          {
              totalProfit = totalProfit + profitelement.GetInvestmentProfit();
              Console.WriteLine("Profit: {0:c}", profitelement.GetInvestmentProfit());
          }
  
          Console.ReadKey();
      }
  }
  </code></pre>
  
  <p><strong><em>Business Domain Entities</em></strong></p>
  
  <pre><code>public interface IBusiness
  {
  
  }
  
  public abstract class EntityBaseClass
  {
  
  }
  
  public interface IRetailBusiness : IBusiness
  {
      double GrossRevenue { get; set; }
  }
  
  public interface IIntellectualRights : IBusiness
  {
      double Royalty { get; set; }
  }
  
  
  
  #region Intellectuals
  public class EngineDesignPatent : EntityBaseClass, IIntellectualRights
  {
      public double Royalty { get; set; }
      public EngineDesignPatent(double royalty)
      {
          Royalty = royalty;
      }
  }
  
  public class BenzolMedicinePatent : EntityBaseClass, IIntellectualRights
  {
      public double Royalty { get; set; }
      public BenzolMedicinePatent(double royalty)
      {
          Royalty = royalty;
      }
  }
  #endregion
  
  #region Retails
  public class BookShop : EntityBaseClass, IRetailBusiness
  {
      public double GrossRevenue { get; set; }
      public BookShop(double grossRevenue)
      {
          GrossRevenue = grossRevenue;
      }
  }
  
  public class AudioCDShop : EntityBaseClass, IRetailBusiness
  {
      public double GrossRevenue { get; set; }
      public AudioCDShop(double grossRevenue)
      {
          GrossRevenue = grossRevenue;
      }
  }
  #endregion
  </code></pre>
  
  <p><strong>REFERENCES</strong></p>
  
  <ol>
  <li><a href="https://stackoverflow.com/questions/8630937/refactor-my-code-avoiding-casting-in-derived-class">Refactor my code : Avoiding casting in derived class</a></li>
  <li><a href="https://stackoverflow.com/questions/1003023/cast-to-generic-type-in-c-sharp">Cast to generic type in C#</a></li>
  <li><a href="https://www.re-motion.org/blogs/mix/2010/05/24/how-a-visitor-implementation-can-handle-unknown-nodes/" rel="noreferrer">How a Visitor implementation can handle unknown nodes</a></li>
  <li><a href="http://blogsprajeesh.blogspot.in/2008/11/open-closed-principle-and-visitor.html" rel="noreferrer">Open Closed Principle and Visitor pattern implementation in C#</a></li>
  </ol>