I am trying to learn how to do events in C#, and according to the MSDN Events tutorial, 


  Events are declared using delegates. If you have not yet studied the Delegates Tutorial, you should do so before continuing


so now I'm trying to understand Delegates first, and failing horribly. What are they for? What problem are you trying to solve where you delegate something?

I THINK they're for passing methods into other methods but what is the point of that? Why not just have a method that does whatever you're doing in the first place?

Passing functions to other functions is a very good way of generalizing code, especially when you have lots of nearly-duplicate code with only the logic in the middle differing. 

My favorite (simple) example of this is making a Benchmark function, that accepts a delegate containing the code you wish to benchmark. I'll be using lambda syntax and Func/Action objects, because they're much more concise (and common) than seeing explicitly created delegates nowadays.

public void Benchmark(int times, Action func)
{
    var watch = new Stopwatch();
    double totalTime = 0.0;

    for (int i = 0; i < times; i++)
    {
        watch.Start();
        func(); // Execute our injected function
        watch.Stop();

        totalTime += watch.EllapsedTimeMilliseconds;
        watch.Reset();
    }

    double averageTime = totalTime / times;
    Console.WriteLine("{0}ms", averageTime);
}


You can now pass in any block of code to that benchmark function (along with the number of times you want to run it) and get back the average execution time!

// Benchmark the amount of time it takes to ToList a range of 100,000 items
Benchmark(5, () =>
{
    var xs = Enumerable.Range(0, 100000).ToList();
});

// You can also pass in any void Function() by its handler
Benchmark(5, SomeExpensiveFunction);


If you couldn't inject the code you wanted to benchmark into the middle of that function, you'd probably end up copying and pasting the logic around anywhere that you wanted to use it.

Linq makes extensive use of function passing, allowing you to have a whole host of really flexible operations on sets of data. Let's take the Where function as an example. It filter's out elements of a list that return "true" when passed a comparison function.

var xs = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

// This function compares each element, and returns true for those that are above 5
//   Result = { 6, 7, 8, 9, 10 }
var above5 = xs.Where((x) => x > 5);

// This function only returns true if an element is even
//   Result = { 2, 4, 6, 8, 10 }
var evens = xs.Where((x) => x % 2 == 0);


The Where function itself very generalized. It simply loops over a collection, and yields a new collection containing only the values that match some predicate function. It's up to you to inject the code that tells it precisely what it's looking for.
