Monday, 22 June 2015

Func Delegate

 In a previous post we talked about declaring delegates:

  • We had to declare a delegate type with a signature and return type 
  • create a function or method that matches the delegate's signature and return type
  • create a function or method that then accepts the your delegate as a parameter
  • pass the delegate or delegates to thee created function
Not just a tad convoluted, but it also clutters up your code; the best code is clean, easy to read, and concise. The kind of code that reads so clearly, that any idiot would say "I could of written that." I'm not a fan of stupid people, but they are everywhere and they will ruin your hard work, that's a fact of life. However that's all the more reason to do a stellar job and hope that your app gets retired before it gets 'Modified' (or in truth butchered by amateurs).

So what are Funcs? As this posts title foreshadows, you can think of them as delegates. Funcs have a return type, and can have multiple parameters. In essence they cut out the middle man of declaring a delegate type, and just let you define a variable inside your functions.


namespace pav.funcExample;

class Program
{
    static int AddFunction(int x, int y)
    {
        return x + y;
    }

    static void Main(string[] args)
    {
        //declared Func
        Func<int, int, int> Add1 = AddFunction;

        //Inline func
        Func<int, int, int> Add2 = (x, y) => { return x + y; };

        Console.WriteLine(Add1(3,4));
        Console.WriteLine(Add2(3,4));    
    }
}


If we take a look at our funcs there are two variations, in the first we assign an existing function to our func, in the second we assign an inline anonymous function, like before this creates a reference to a function, letting us pass them around like variables.

now that's all fun and dandy and yes it can shorten your code a bit, but where's the real value in this? to answer that let's take a look at our previous example from delegates now using the func and action keywords instead.


namespace pav.funcExample;

class Program
{
    struct Employee
    {
        public string FirstName;
        public string LastName;

        public Employee(string FirstName, string LastName)
        {
            this.FirstName = FirstName;
            this.LastName = LastName;
        }
    }

    class EmployeeService
    {
        public List<Employee> Employees { get; } = new List<Employee>() {
                new Employee("Pawel","Chooch"), new Employee("Steve","Smith"),
                new Employee("Ian","Price"), new Employee("Tomek","Wan"),
                new Employee("Jacques","Cocion") };

        public void ProcessEmployee(Func<Employee, string> formatEmployee)
        {
            if (formatEmployee != null)
                foreach (Func<Employee, string> del in formatEmployee.GetInvocationList())
                    foreach (var e in Employees)
                        Console.WriteLine(del(e));
        }
    }

    static void Main()
    {
        var es = new EmployeeService();

        Func<Employee, string> formatFunc = null;
       
        formatFunc += e => $"{e.FirstName} {e.LastName}";
        formatFunc += e => $"{e.FirstName.Substring(0, 1)}. {e.LastName}";

        es.ProcessEmployee(formatFunc);
    }
}


In the above we've reduced the number of lines and increased readability, funcs in short let us reference