This post originated from an RSS feed registered with .NET Buzz
by -.
Original Post: Anonymous Delegates
Feed Title: Norbert Eder - Living .NET
Feed URL: http://feeds.feedburner.com/NorbertEder-Livingnet
Feed Description: Copyright (c)2005, 2006 by Norbert Eder
Dem einen oder anderen mögen anonyme Methoden (oder beispielsweise anonyme Typen wie sie mit C# 3.0 kommen) bekannt sein. In diesem Beitrag möchte ich ein wenig über anonyme Delegates schreiben und wozu diese benötigt werden (sind ohnehin sehr ähnlich zu anonymen Methoden).
Zuerst gleich das Beispiel, anhand dessen die Erklärungen vorgenommen werden:
using System;
using System.Collections.Generic;
using System.Text;
namespace AnonymousDelegatesSample
{
publicclass Book
{
publicstring Title;
publicdecimal Price;
}
publicclass Person
{
publicstring Firstname;
publicstring Lastname;
public List<Book> BookList;
publicdecimal Discount;
public DiscountCalculator CalculationMethod;
}
publicdelegatedecimal DiscountCalculator(decimal price);
publicclass Example
{
privatedecimal CalculateDiscount(decimal price)
{
return price * newdecimal(0.05);
}
publicvoid ShowExample()
{
DiscountCalculator default_calc =
new DiscountCalculator(CalculateDiscount);
DiscountCalculator specialcustomer_calc =
delegate(decimal price)
{
return price * newdecimal(0.09);
};
Book book1 = new Book();
book1.Title = "ASP.NET for dummies";
book1.Price = newdecimal(35.99);
Book Book2 = new Book();
Book2.Title = "C# for dummies";
Book2.Price = newdecimal(49.99);
List<Book> bookList = new List<Book>();
bookList.Add(book1);
bookList.Add(Book2);
List<Person> personList = new List<Person>();
Person person1 = new Person();
person1.Firstname = "Norbert";
person1.Lastname = "Eder";
person1.BookList = bookList;
person1.CalculationMethod = specialcustomer_calc;
personList.Add(person1);
Person person2 = new Person();
person2.Firstname = "Alf";
person2.Lastname = "Dudldei";
person2.BookList = bookList;
person2.CalculationMethod = default_calc;
personList.Add(person2);
foreach (Person p in personList)
{
decimal price = 0;
foreach (Book b in p.BookList)
price += b.Price;
p.Discount = p.CalculationMethod(price);
Console.WriteLine(
String.Format("{0} {1}:t {2} discount",
p.Firstname,
p.Lastname,
p.Discount.ToString()));
}
Console.WriteLine("Press any key ...");
Console.ReadKey();
}
}
}
Zuerst ein kurze Erklärung wozu dieses Beispiel dient: Grundsätzlich gibt es zwei Klassen. Zum einen die Person und zum anderen das Book. Wir gehen also davon aus, dass eine Person Bücher kauft und diese in einer Collection aufbewahrt werden. Nun soll (je nach Kundenstatus) ein Rabatt berechnet werden.
Zur Erklärung: Dies kann natürlich auch auf eine andere - vermutlich einfachere Art und Weise implementiert werden. Dieses Beispiel dient lediglich der Veranschaulichung von anonymen Delegates.
Grundsätzlich ist in diesem Beispiel ein üblicher Delegate definiert:
Nun kann es jedoch vorkommen, dass eine spezielle Berechnung durchgeführt werden muss, diese wird nur in einem ganz bestimmten Fall angewandt und bedarf daher keiner eigenen Methoden-Implementierung (in diesem Beispiel vielleicht weniger sinnvoll, aber generell treten bei der Verwendung von Delegates immer wieder Fälle auf, in denen sich eine eigene Methode nicht rentiert). Hier kommen nun anonyme Delegates ins Spiel. Die aufgerufene Methode ist hierbei ansich nicht vorhanden (daher anonym) und wird erst bei der Erstellung des Delegate definiert. Wie hier:
Damit wird im Grunde erreicht, dass die eigentliche Berechnung durch eine neue ersetzt wird. Eine entsprechende Methode muss hierzu nicht vorhanden sein.
Einsatzgebiete hierfür finden sich immer wieder, daher grundsätzlich nicht schlecht, wenn man sie kennt und auch anwenden kann. Im Falle des Falles muss der Entwickler ohnehin selbst entscheiden ob dies sinnvoll ist oder nicht. Wird die Berechnung anderweitig verwendet ist es sicherlich sinnvoll, diese in eine eigene Methode zu kapseln. Andernfalls kann durchaus ein anonymer Delegate verwendet werden.