Pages

Thursday, December 31, 2020

c# Delegates

Delegates are methods that are passed in as a parameter. Now, you can change the implementation of the method that is passed in from a different part of the code. For instance, "mentionSubTotal" can be implemented differently (discount is applied differently) from another location. 

Delegates are pointers to functions. But what is the purpose of calling functions indirectly (passing them in) via delegates versus calling that same function directly? 

Delegates are used to communicate between two parties. The main use of delegates are callbacks, callbacks, callbacks ...  

public class ShoppingCartModel

    {

        public delegate void MentionDiscount(decimal subTotal);

        public List<ProductModel> Items { get; set; } = new List<ProductModel>();

        

        // These are the 3 types of delegates.

        // 1) MentionDiscount is the "raw" delegate

        // 2) Func takes params (up to 16) and returns a value. No out params allowed.

        // 3) Action takes params (up to 15) and returns void. 


// Here is example using all 3 forms. Generally, you would only use one delegate, not 3). 

        public decimal GenerateTotal(MentionDiscount mentionSubtotal,

            Func<List<ProductModel>, decimal, decimal> calculateDiscountedTotal,

            Action<string> tellUserWeAreDiscounting)

        {

            decimal subTotal = Items.Sum(x => x.Price);


            mentionSubtotal(subTotal);


            tellUserWeAreDiscounting("We are applying your discount.");


            return calculateDiscountedTotal(Items, subTotal);  // returns decimal

        }

    }


From the calling method side, there are 2 ways to do.

1) You can create the method and pass in the method name:

Console.WriteLine($"Shopping cart subtotal: {cart.GenerateTotal(SubTotalAlert, CalculateLeveledDiscount, AlertUser):C2}");

All 3 methods will be defined in the class. For example, SubTotalAlert is defined here and passed as a parameter above.

private static void SubTotalAlert(decimal subTotal)

        {

            Console.WriteLine($"The subtotal is {subTotal:C2}");

        }


2) Instead of defining methods, you can write anonymous functions inline. All 3 methods are written as inline parameters and passed as parameters. 

decimal total = cart.GenerateTotal((subTotal) => Console.WriteLine($"The subtotal for cart 2 is {subTotal:C2}"),

                (products, subTotal) => {

                    if(products.Count > 3)

                    {

                        return subTotal * 0.5M;

                    }

                    else

                    {

                        return subTotal;

                    }

                },

                (message) => Console.WriteLine($"Cart 2 Alert: { message }"));

No comments:

Post a Comment