Why would I ever use delegates if I’m not doing events? [duplicate]

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?

12

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.

2

Suppose you have a complicated mathematical calculation to do, that involves performing rounding. Suppose that sometimes you want the rounding to be round to even (aka bankers’ rounding), but other times you want round away from zero (aka ’round up [in absolute value]’).

Now, you could write two methods:

double DoTheCalculationWithRoundToEven(double input1, double input2)
{
    var intermediate1 = Math.Pow(input1, input2);
    // more calculations...
    var intermediate5 = Math.Round(intermediate4, MidpointRounding.ToEven);
    // more calculations...
    var intermediate10 = Math.Abs(intermediate9);

    return intermediate10;
}

double DoTheCalculationWithRoundAwayFromZero(double input1, double input2)
{
    var intermediate1 = Math.Pow(input1, input2);
    // more calculations...
    var intermediate5 = Math.Round(intermediate4, MidpointRounding.AwayFromZero);
    // more calculations...
    var intermediate10 = Math.Abs(intermediate9);

    return intermediate10;
}

with the two methods being the same except for that one line in the middle.

Now, this works, BUT you’ve got duplicated code and the very real possibility that some future maintainer (for example, a future you) will change one version of the intermediate2 to intermediate3 and forget about the other.

A delegate type and parameter can solve this duplication.

First declare the delegate type:

    public delegate double Rounder(double value);

This says that a Rounder is a method that accepts a double and returns a double.

Next, have one calculation method that accepts a Rounder and uses it to round:

double DoTheCalculation(double input1, double input2, Rounder rounder)
{
    var intermediate1 = Math.Pow(input1, input2);
    // more calculations...
    var intermediate5 = rounder(intermediate4);
    // more calculations...
    var intermediate10 = Math.Abs(intermediate9);

    return intermediate10;
}

Finally, when you want the calculation done, pass an appropriate Rounder. You can spell it all out with methods:

double RounderAwayFromZero(double value)
{
    return Math.Round(value, MidpointRounding.AwayFromZero);
}
// same for ToEven

then call one of:

var result = DoTheCalculation(input1, input2, RounderAwayFromZero);

or

var result = DoTheCalculation(input1, input2, RounderToEven);

but C# allows you to do this all inline with lambdas:

var result = DoTheCalculation(input1, input2, 
     value => Math.Round(value, MidpointRounding.AwayFromZero));

where the lambda expression defines a method with the correct signature to be a Rounder.

6

Delegates are similar to interfaces. You are simply defining a contract which can be fulfilled by whatever is consuming the class that uses the delegate. The big difference between an interface and a delegate is an interface defines a contract for an entire class while a delegate defines a contract for a single method.

The best, most basic real world example of using delegates is the “Hole in the Middle” pattern. I don’t need this pattern very often, but when I do, it’s extremely valuable. You can accomplish this same pattern using inheritance and abstract methods, however, delegates allow you to accomplish this using composition.

public delegate void MyDelegate(string param1, string param2);

public void SomeMethod(string param1, string param2) {
    Console.WriteLine(param1);
    //do some more work
}

public void DoSomething(MyDelegate somemethod) {
    //do something here
    somemethod(param1, param2);
    //do something else here
}

Delegates act as a way to parametrize some kind of action. The function that is being passed a delegate doesn’t care how the action is done, just that it is performed.

For example, look at the IComparer interface. It allows you to sort a list without relying on how the type in the list is “naturally” sorted. However, when you look at the interface, it only defines one method. It seams rather wasteful to define a whole class that only implements a single function.

Delegates solve this problem1. You won’t need to define a class, just the method. It allows you to remove boilerplate code and focus on what you want to do. Lambdas take this a step forward so that the function definition can be in-lined instead of defined somewhere else in the class.

1 If you look at Sort(), an overloaded version exists that uses a delegate.

3

The purpose of passing a method to another method is to separate the purposes of those two methods. This is in keeping with accepted principles of object-oriented design, specifically the Single Responsibility Principle: “a code object should do one thing, and be the only code object in the codebase that does that thing”.

Case in point, let’s say you have a method that reads a file in a certain format (let’s say pipe-delimited text), and a method that digests the information in that file in a specific way to extract some information. You say you should put these together in one method. Well, what happens when the program needs to start reading from CSV files? What happens when you need a different subset of the data contained in it? You need to change the method. But the program still needs to handle pipe-delimited text and pull the older set of data. Now you have one method that reads from two different file types and produces two different sets of data. This method is rapidly on its way to becoming unmaintainable.

Instead, you can create a method that reads pipe-delimited text, and another that reads CSVs. You can create a method that extracts one data set, and another that extracts the second. Then, you can give the file-reading method as a delegate to the data extraction method, or vice versa. Or, you can give them both to a third class of method that will simply execute them in order, giving the data from the file to the dataset-extracting method.

By dong this, you increase the number of methods you’re writing, but each method has one and only one purpose. Any change you need to make so that the method works properly won’t affect the purpose or execution of any other. The resulting code is easier to understand, easier to maintain, and thus will require less testing in order to ensure its correctness.

There are a ton of framework class library types with operations that take delegates as a parameter.

If you use the Task parallel Library, LINQ or Entity Framework, you will be passing in delegates as arguments.

A lot of the delegate signatures you would want to use are already defined (Action, Func, Predicate) and the syntax made simpler with lambda expressions.

7

Probably the simplest way to understand delegates and events is to look at GUI programming. Let’s take a very common case: you have a form with a button on it, and when the user clicks the button, you want a certain piece of code to execute.

The guy who wrote the button class has no idea what you want to do with it, obviously. So he can’t build your code for “what this button should do” into his class. And even if he could, he really shouldn’t, because then it stops being a “GUI button” and turns into a “Medivh’s this-specific-use-case button” which is much less useful in the general case.

So instead, the guy who wrote the button class put in an Event, which is sort of a hook into the functionality of the object. An Event is basically a piece of the code that’s being executed where someone else can stick code in there. So when someone clicks the button, it fires the OnClick event, and if you’ve attached anything to that event–such as a method (a delegate) that causes a new form to open–then that delegate will be executed at this point.

When you start thinking of methods as not just a procedure or function you can call, but an object you can pass to other code, it opens up all sorts of new possibilities. Some of the other people here have already mentioned LINQ and the Task Parallel Library, which contain algorithms that define the basic idea of something, and then let you pass in a delegate to fill in the details.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật