C# Case Study – Delegate as a Method in Practice

Case Background

A courier company ships parcels in the local area. There are four zones in the company’s business area. The shipping fees are a certain percentage of the given item price. Some destinations are a bit dangerous or far from the company’s depot, which has an additional risk fee $25.

  • Zone 1 – 25%
  • Zone 2 – 12%. Zone 2 is a dangerous area and it imposes $25.
  • Zone 3 – 8%
  • Zone 4 – 4%. Zone 4 is a dangerous area and it imposes $25.

Approach

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegatesSolution
{
    class Program
    {
        static void Main(string[] args) {

            ShippingFeesDelegate theDel;
            ShippingDestination theDest;

            string theZone;
            do {              
                Console.WriteLine("What is the destination zone?");
                theZone = Console.ReadLine();

                if (!theZone.Equals("exit")) {               
                    theDest = ShippingDestination.getDestinationInfo(theZone);
                  
                    if (theDest != null) {
                        
                        Console.WriteLine("What is the item price?");
                        string thePriceStr = Console.ReadLine();
                        decimal itemPrice = decimal.Parse(thePriceStr);

                        theDel = theDest.calcFees;

                        if (theDest.m_isHighRisk) {
                            theDel += delegate(decimal thePrice, ref decimal itemFee) {
                                itemFee += 25.0m;
                            };
                        }

                        //CALCULATION STARTS FROM HERE
                        decimal theFee = 0.0m;
                        theDel(itemPrice, ref theFee);
                        Console.WriteLine("The shipping fees are: {0}", theFee);
                    }
                    else {
                        Console.WriteLine("Hmm, you seem to have entered an uknown destination. Try again or 'exit'");
                    }
                }
            } while (theZone != "exit");
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DelegatesSolution
{
    
    public delegate void ShippingFeesDelegate(decimal thePrice, ref decimal fee);

    abstract class ShippingDestination
    {
        public bool m_isHighRisk;
        public virtual void calcFees(decimal price, ref decimal fee) {}

        
        public static ShippingDestination getDestinationInfo(string dest) {
            if (dest.Equals("zone1")) {
                return new Dest_Zone1();
            }
            if (dest.Equals("zone2")) {
                return new Dest_Zone2();
            }
            if (dest.Equals("zone3")) {
                return new Dest_Zone3();
            }
            if (dest.Equals("zone4")) {
                return new Dest_Zone4();
            }
            return null;
        }
    }

    class Dest_Zone1 : ShippingDestination
    {
        public Dest_Zone1() {
            this.m_isHighRisk = false;
        }
        public override void calcFees(decimal price, ref decimal fee) {
            fee = price * 0.25m;
        }
    }

    class Dest_Zone2 : ShippingDestination
    {
        public Dest_Zone2() {
            this.m_isHighRisk = true;
        }
        public override void calcFees(decimal price, ref decimal fee) {
            fee = price * 0.12m;
        }
    }

    class Dest_Zone3 : ShippingDestination
    {
        public Dest_Zone3() {
            this.m_isHighRisk = false;
        }
        public override void calcFees(decimal price, ref decimal fee) {
            fee = price * 0.08m;
        }
    }

    class Dest_Zone4 : ShippingDestination
    {
        public Dest_Zone4() {
            this.m_isHighRisk = true;
        }
        public override void calcFees(decimal price, ref decimal fee) {
            fee = price * 0.04m;
        }
    }
}

Study Note

In the Program.cs, we use a basic structure as logic to implement the solution. The do-while ensures the program running till use type in exit.

string theZone;
do {
//Implementation
} while(theZone != "exit");

In the do-while statement, we retrieve a ShippingDestination object to represents a shipping zone. How do we do that? Have a look the following code snippet in ShippingInfo.cs

abstract class ShippingDestination
    {
        public bool m_isHighRisk;
        public virtual void calcFees(decimal price, ref decimal fee) {}

        
        public static ShippingDestination getDestinationInfo(string dest) {
            if (dest.Equals("zone1")) {
                return new Dest_Zone1();
            }
            if (dest.Equals("zone2")) {
                return new Dest_Zone2();
            }
            if (dest.Equals("zone3")) {
                return new Dest_Zone3();
            }
            if (dest.Equals("zone4")) {
                return new Dest_Zone4();
            }
            return null;
        }
    }

We use keyword abstract to declare an abstract class to prevent it from being instantiated by itself. We can’t create a ShippingDestination class object; we have to create a subclass to represent a zone. This is an excellent approach for the cleaning code practice.

As a result, when user types in a zone, we will have a designated zone object as a subclass object of ShippingDestination class.

In regard to shipping fee calculation, we use a delegate to calculate and manipulate the shipping fee for us. How?

In each of the ShippingDestination’s subclass, we have a method called public override void calcFees(decimal price, ref decimal fee). It shares the same signature with delegate public delegate void ShippingFeesDelegate(decimal thePrice, ref decimal fee).

We use a reference variable so that we can return the calculated value and it can be further manipulated by another delegate.

In the Program.cs file, we assign a specific zone’s fee calculate method to our delegate. It passes a reference variable, which can be further manipulated if needed.

When we need to calculate the fee in a dangerous area, we use an anonymous delegate in line to further modify shipping fee to include an additional $25.

theDel = theDest.calcFees;
if (theDest.m_isHighRisk) {
     theDel += delegate(decimal thePrice, ref decimal itemFee) {
           itemFee += 25.0m;
         };
}

In the end, we define a local variable that will hold the result, then we invoke the delegate.

decimal theFee = 0.0m;
theDel(itemPrice, ref theFee);
Console.WriteLine("The shipping fees are: {0}", theFee);

Delegate is a heavily used techniques in development, it can take time to sink in. Good Luck 🙂 Happy programming.


1 Reply to “C# Case Study – Delegate as a Method in Practice”

  1. Dzięki za wskazówki dotyczące naprawy kredytu na temat tego wszystkiego blogu. Co ja chciałbym rada ludziom jest zrezygnować z tej mentalności że mogą teraz i zapłać później. As a as be a} społeczeństwo {my|my wszyscy|my wszyscy|wielu z nas|większość z nas|większość ludzi} ma tendencję do {robienia tego|robienia tamtego|próbowania tego|zdarzyć się|powtórz to} dla wielu {rzeczy|problemów|czynników}. Obejmuje to {wakacje|wakacje|wypady|wyjazdy wakacyjne|wycieczki|rodzinne wakacje}, meble, {i|jak również|a także|wraz z|oprócz|plus} przedmiotów {chcemy|chcielibyśmy|życzymy|chcielibyśmy|naprawdę chcielibyśmy to mieć}. Jednak {musisz|musisz|powinieneś|powinieneś chcieć|wskazane jest, aby|musisz} oddzielić {swoje|swoje|to|twoje obecne|swoje|osoby} chcą {od wszystkich|z potrzeb|z}. {Kiedy jesteś|Kiedy jesteś|Kiedy jesteś|Jeśli jesteś|Tak długo, jak jesteś|Kiedy} pracujesz, aby {poprawić swój kredyt|poprawić swoją zdolność kredytową|zwiększyć swój kredyt|zwiększyć swój kredyt|podnieś swój ranking kredytowy|popraw swój kredyt} wynik {musisz zrobić|zrobić|faktycznie potrzebujesz|naprawdę musisz} dokonać kilku {poświęceń|kompromisów}. Na przykład {możesz|możesz|możesz|możesz|będziesz mógł|| możesz|prawdopodobnie możesz} robić zakupy online {aby zaoszczędzić pieniądze|aby zaoszczędzić pieniądze|aby zaoszczędzić} lub {możesz przejść do|może się zwrócić|może odwiedzić|może obejrzeć|może sprawdzić|może kliknąć} używane {sklepy|sklepy|detaliści|sprzedawcy|punkty sprzedaży|dostawcy} zamiast {drogie|drogie|drogie|drogie|drogie|drogich} domów towarowych {dla|w odniesieniu do|dotyczących|odnoszących się do|przeznaczonych dla|do zdobycia} odzieży {strzykawki insulinowe 1ml|strzykawki tuberkulinowe|strzykawki|strzykawka|strzykawki insulinowe|strzykawki do insuliny|strzykawki trzyczęściowe tuberkulinowe|strzykawka tuberkulinowa|strzykawka insulinowa|strzykawka do insuliny|strzykawka trzyczęściowe tuberkulinowa} {strzykawki insulinowe 1ml|strzykawki tuberkulinowe|strzykawki|strzykawka|strzykawki insulinowe|strzykawki do insuliny|strzykawki trzyczęściowe tuberkulinowe|strzykawka tuberkulinowa|strzykawka insulinowa|strzykawka do insuliny|strzykawka trzyczęściowe tuberkulinowa}.

Leave a Reply

Your email address will not be published. Required fields are marked *