This post is kind of not LINQ related, kind of LINQ related.

I’ve mentioned lambdas before but wanted to move more into what is more at the core of lambdas. That is more along the lines of delegates.

We all know about delegates, don’t we?

“No Brian, we don’t.”

“Ivan is that you?” (Yes, I’ve named my inner voice Ivan, IV, inner voice, Ivan, get it?)

“Yes”

“Um, is that all?”

“What else do you want me to say? I want to know about delegates”

Ok, well, then, delegates are basically pointers to methods.

Let me give you an example:

public partial class Window1 : Window
{
    delegate int del(int i);

    public Window1()
    {
        del myDelegate = x => x * x;
        int square = myDelegate(5);
    }
}

You can see here that I have defined my type for the delegate below the class declaration

delegate int del(int i);

The delegate, myDelegate, takes an int and returns an int. Then inline with anycode I can define a method that uses these parameters.

Now I could do something like:

del myDelegate2 = x => --x;
int decrement = myDelegate2(4);

but without having to declare a delegate type let’s take a look at Func so we can create functions inline without having to declare a delegate type first. We technically are declaring a type because of generics and we are limited to the small set of parameters that Func allows us, but that’s neither here nor there since I would assume, for an inline query this should be able to handle your needs. If you can’t do it in what Func provides I suspect you will probably just do a standard method.

Func types are:

Func(TResult) Delegate
Func(T, TResult) Delegate
Func(T1, T2, TResult) Delegate
Func(T1, T2, T3, TResult) Delegate
Func(T1, T2, T3, T4, TResult) Delegate

So let’s take a look at some code:

int[] list1 = { 0, 1, 2, 3, 4, 5 };
Func<int, bool> lookForEven = x => x % 2 == 0;
var myListOfEvens = list1.Where(lookForEven);

The Where method in the int list takes Func predicate. (It will take Func predicate as well). So I created the method lookForEven with a lambda, x => x % 2 == 0, and then I can use it in the Where method. Now, the operations of the method don’t have to be defined inline. They can be a method that matches the types of the declaration.

private bool BadlyNamedMethod(int val)
{
    return Math.Pow(val, 2) < 20;
}

private void TestMyMethod()
{
    int[] list1 = { 0, 1, 2, 3, 4, 5 };
    var sqrsLessThenTwenty = list1.Where(BadlyNamedMethod);
}

Now let’s look at taking multiple inputs:

int[] list1 = { 0, 1, 2, 3, 4, 5 };
int[] list2 = { 0, 2, 4, 6, 8 };
Func<int, int, bool> myFunc = (x,y) => x == y;
foreach (var x in list1)
{
    foreach (var y in list2)
    {
        if (myFunc(x, y))
        {
            MessageBox.Show("Found Match");
            break;
        }
    }
}

Basically I’m creating an intersect.

“Brian, there is an intersect function already.”

“Yes Ivan, I know”

“Fine, f-off”

Yes, yes, yes, as Ivan pointed out I could just as easily done: var myListOfEquals = list1.Intersect(list2);

but then you wouldn’t see me using the Func.

Basically, I’m creating a function that takes two parameters, x and y, and testing for equality. The system knows what I’m going to do becuase when I created “myFunc” I defined that it would take int, int and return bool.

But we’re not limited to primitives.

private void TestMyMethod()
{
    Person[] people = {new Person {FirstName = "Brian", LastName = "Mullen", Id = 1},
			   new Person {FirstName = "George", LastName = "Smith", Id = 2},
			   new Person {FirstName = "Mabel", LastName = "Jones", Id = 3}};

    Func<Person, string> compareByName = p => p.LastName;
    var orderedByLastName = people.OrderBy(compareByName);
}

Want to compare people by a list of strings?

Func<Person, string, int?> personCompare = (x, y) =>
{
    if (x.FirstName == y)
        return x.Id;
    return null;
};

Anyways, have to go. But hopefully this is a nice introductory look to delegates, Func and some lambdas.

Brian

Leave a Reply

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

FormatException

928 East Plymouth Drive Asbury Park, NJ 07712