DEV Community

Ellie
Ellie

Posted on

Actions — delegates that return void

Before Make sure to read about delegate here

Action is just a built‑in delegate for “do something and don’t return a value.” So Action is the same shape as a custom delegate that returns void.

If delegates are “function references,” then Action is the ready‑made one for void.

Same example as delegate, using Action

// Built-in delegate: Action<T> == delegate void Something(T)
static void FormalSay(string name)   => Console.WriteLine($"Hello, {name}.");
static void FriendlySay(string name) => Console.WriteLine($"Hey {name}!");

Action<string> say = FormalSay;   // reference to a void-returning function
say("Ava");                       // Hello, Ava.

say = FriendlySay;                 // swap behaviour
say("Ava");                       // Hey Ava!
Enter fullscreen mode Exit fullscreen mode

▶️ Tiny runnable sample

welldone if you have reached here, bellow I'm trying to explain the action in an example more closed to real world(the same example as delegate)

Scenario: train ticket AddOns with Action

Imagine you have a Train ticket and you want to add some Extras to your ticket such as Insurance, Coffee , ...
let's write this code without Actions and then with Actions.

Basics:

First Lets have TrainTicket Model:

public class TrainTicket
{
    public string TicketId { get; }
    public decimal Price { get; set; }  // base + add-ons    
    public decimal Discount { get; set; }   // from promo
    public decimal FinalPrice => Price - Discount;
    public List<string> Extras { get; } = new();

    public TrainTicket(string ticketId, decimal basePrice)
    {
        TicketId = ticketId;
        Price = basePrice;
    }
}
Enter fullscreen mode Exit fullscreen mode

and now Let's consider we have these AddOns:

public static class TrainAddOns
{
    public static void AddInsurance(TrainTicket ticket)
    {
        ticket.Price += 7m; 
        ticket.Extras.Add("Insurance");
    }

    public static void CoffeeToSeat(TrainTicket ticket)
    {
        ticket.Price += 3m;
        ticket.Extras.Add("Coffee to seat");
    }

    public static void FoodDelivery(TrainTicket ticket)
    {
        ticket.Price += 8m; 
        ticket.Extras.Add("Food delivered to seat");
    }

    public static void ExtraLegroom(TrainTicket ticket)
    {
        ticket.Price += 12m;
        ticket.Extras.Add("Extra legroom");
    }
}
Enter fullscreen mode Exit fullscreen mode

Apply AddOns Without Actions

We get a addOns as a string and add the extras with a switch statement:

public  static TrainTicket ApplyAddOns(TrainTicket ticket, IEnumerable<string> addOns)
    {
        foreach (var name in addOns)
        {
            switch (name)
            {
                case "insurance":
                {
                    TrainAddOns.AddInsurance(ticket);
                    break;
                }
                case "coffee":
                {
                    TrainAddOns.CoffeeToSeat(ticket);
                    break;
                }
                case "food":
                {
                    TrainAddOns.FoodDelivery(ticket);
                    break;
                }
            }
        }
        return ticket;
    }

Enter fullscreen mode Exit fullscreen mode

and here is how we call this method to apply addons:

ApplyAddOns(ticket, new List<string> { "insurance", "coffee", "food" });
Enter fullscreen mode Exit fullscreen mode

Apply AddOns With Actions

What makes the code more simple is using the code and passing the actions( ref to void function) to the ApplyAddOns method. this Method doesn't need to know the implementation, it will call the action so that it can apply the AddOns as expected.

public  static TrainTicket ApplyAddOns(TrainTicket ticket, List<Action<TrainTicket>> addOnActions)
    {
        foreach (var addOnAction in addOnActions)
        {
            addOnAction(ticket);
        }
        return ticket;
    }

Enter fullscreen mode Exit fullscreen mode

and here is how we call this metgod to apply addons:

ApplyAddOns(ticket,new List<Action<TrainTicket>>
        {
            TrainAddOns.AddInsurance,
            TrainAddOns.CoffeeToSeat,
            TrainAddOns.FoodDelivery
        });

Enter fullscreen mode Exit fullscreen mode

▶️ Runnable sample: Apply AddOns Without Action
▶️ Runnable sample: Apply AddOns With Action

Top comments (0)