Delegates2 min read

Today i’ll be writing about one of great C# features, called DELEGATES.

What is delegate?

Delegate is a reference to a function or, better to say, a blueprint of a function which gives us the abillity to extend already implemented functionalities with some of our very own methods.
Imagine we use some framework which already has some functionalities i.e. card processing. If we want to extend with additional functionalities it’s pretty straightforward thing to do using delegates.
Without using delegates our card processing framework should be recompiled every time we add new functionality, but using delegates our framework does not depend on other functionalities and is not necessary to recompile and redeploy each time we add new functionality.

When using delegates, first we need to define delegate type (void, string, int…). In our card processing demo we will use void as a type.

public class CardProcessor {    
    public delegate void DelegateCardHandler(Card card);    
    public void Process(Card card, DelegateCardHandler cardHandler) {
        var card = new Card();
        cardHandler(card);
        card.Save();
	}
}
public class Card {
    	public void Save() {}
}

public class CardHandlers {
    public void AddImageToCard() {
        Console.Writeline("Added image");
    }

    public void AddAditionalTextToCard() {
        Console.Writeline("Added text");
    }

    public void ResetCard() {

        Console.Writeline("Card reset");
    }

    public void DeleteCard() {

        Console.Writeline("Card deleted");
    }
}


class Program {
    static void Main(string[] args) {
        var cardProcessor = new CardProcessor();
        var cardHandlers = new CardHandlers();

        CardProcessor.DelegateCardHandler cardHandler = cardHandlers.AddImageToCard;
        cardHandler += cardHandlers.AddAditionalTextToCard;
        cardHandler += cardHandlers.ResetCard;
        cardHandler += cardHandlers.DeleteCard;
        cardHandler += ZipCard;
        


        // dummy method  
        var card = RetrieveCard();

        cardProcessor.Process(card, cardHandler);
    }


    private Card RetrieveCard() {
        Console.Writeline("Card retrieved");
    }


    // adding new Card Handler Functionality - method should have the same signature as delegate type

    static void ZipCard() {
        Console.Writeline("Card zipped");
    }
}

Lately in C#, we tend to use generic delegates: Action or Func instead of delegate type, which is cleaner and easier to use.
Action is used for void types and Func for any other types.

Action is a generic delegate  to a method, that takes zero, one or more input parameters, but does not return anything.

Func is a generic delegate to a method, that takes zero, one or more input parameters, and returns a value (or reference).
Last param in Func is always a return type.

i.e.:

 Func<int, double> foo

Sample of code rewritten to use generic Action delegate:

public class CardProcessor {    
  
    public void Process(Card card, Action<Card> cardHandler) {
        var card = new Card();
        cardHandler(card);
        card.Save();
 }
}


class Program {
    static void Main(string[] args) {
        var cardProcessor = new CardProcessor();
        var cardHandlers = new CardHandlers();

        Action<Card> cardHandler = cardHandlers.AddImageToCard;
        cardHandler += cardHandlers.AddAditionalTextToCard;
        cardHandler += cardHandlers.ResetCard;
        cardHandler += cardHandlers.DeleteCard;
        cardHandler += ZipCard;
        


        // dummy method  
        var card = RetrieveCard();

        cardProcessor.Process(card, cardHandler);
    }

Summary:

We use delegate when:

  • using event design pattern
  •  the caller doesn’t need to access other properties or methods on the object implementing the method

Leave a Reply

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