来博客园一年多了,貌似从来没看过有一篇English Technical Article(英文技术文章)发布在首页的,看到的全是母语版。不过,有一次,看到了一篇老外写的,竟被翻译成中文,可能译者还是为了大部分人着想吧,可惜。
我想了想,为了广大想提高英语的程序员们(偶也是),提高英语的好处,就不说了吧。建议博客园,一周也有同志发几篇英文贴在首页,不管是讨论技术的,还是其他的方面的,或是从国外拷贝的,是英文的就好,难懂的单词还可以注释下,这样可以节省朋友们读英语文章的时间。一个目的:让同志们不用到外国站点,也可以欣赏到原汁原味的英文,还可以提交英文水平!
Improve your English from now on!
下面是我的demo
摘自codeproject
引用地址:http://www.codeproject.com/KB/cs/DelegatesOMy.aspx
C# Delegates, Anonymous Methods, and Lambda Expressions – O My!
Introduction
Delegates, anonymous methods, and lambda expressions can be very confusing(迷惑的) in .NET. I think this is proven(证明) in code like the example below. Which one of the calls to First
compiles? Which one returns the answer we are looking for; namely(即,也就是)the Customer with the ID 5. The answer, incidentally(偶然地), is that all six calls to First
not only compile, but all find the correct customer and are functionally equivalent(相等的). If you are at all confused as to why this is true, this article is for you.
class Customer
{
public int ID { get; set; }
public static bool Test(Customer x)
{
return x.ID == 5;
}
}
...
List<Customer> custs = new List<Customer>();
custs.Add(new Customer() { ID = 1 });
custs.Add(new Customer() { ID = 5 });
custs.First(new Func<Customer, bool>(delegate(Customer x) { return x.ID == 5; }));
custs.First(new Func<Customer, bool>((Customer x) => x.ID == 5));
custs.First(delegate(Customer x) { return x.ID == 5; });
custs.First((Customer x) => x.ID == 5);
custs.First(x => x.ID == 5);
custs.First(Customer.Test);
The setup(装备,安装) – What are delegates?
Ok, so you've got a shopping cart(购物车) class that processes a customer's order. Management(管理部门) has decided to give people discounts(折扣) based on volume, price, etc. As part of this, they have implemented(执行) a factor that you must use when calculating(计算,处理) an order. Ok, no big deal, you simply declare a variable to hold the ‘magic discount’ and proceed(沿特定路线前进) to code your algorithm(算法).
Well, the next day, management, in their infinite(无限的) wisdom(智慧), decides to change the discount amount based on the time of day; brilliant(卓越的), I know. That's easy enough, however, so you simply make the changes in your code.
class ShoppingCart
{
public void Process()
{
int magicDiscount = 5;
if (DateTime.Now.Hour < 12)
{
magicDiscount = 10;
}
}
}
The following day, management once again changes things and adds even more logic (or il-logic) into the discount algorithm. ‘That's enough’ ,you say to yourself. How can I get this ridiculous (荒谬的)algorithm out of my code and let someone else maintain(保持) the logic? What you want to do is hand over(交出,移交), or delegate, the responsibility to someone else. Fortunately, .NET has a mechanism(机制) to do this called, you guessed it, delegates.
Delegates
If you have a C/C++ background, the best way to describe delegates is to call them function pointers. For everyone else, think of them as a way to pass methods the same way you pass values and objects around. For example, the three lines below embody the same basic principle(原则): you are passing, but not using, a piece of data to be used by the Process
method.
// passing an integer value for the Process method to use
Process( 5 );
// passing a reference to an ArrayList object for the Process method to use
Process( new ArrayList() );
// passing a method reference for the Process method to call
Process( discountDelegate );
OK, so what is discountDelegate
and how do I create one? How does the Process
method use a delegate? The first thing we need to do is declare a delegate type in the same way we declare a class.
delegate int DiscountDelegate();
What this means is we now have a delegate type called DiscountDelegate
that we can use in the same way we can use a class, struct, etc. It takes no parameters, but returns an integer. Just like a class, however, it isn't very useful until we create an instance of it. The trick(诀窍,欺骗) to creating an instance of a delegate is to remember that a delegate is nothing more than a reference to a method. The key here is to realize that even though DiscountDelegate
does not have any constructors, when creating one, there is an implicit(隐式的) constructor that wants a method matching its signature (no params, returning int). How do you ‘give’ the constructor(构造器) a method? Well, .NET lets you simply type in the name in the same way you would call the method; all you do is omit the parentheses(忽略圆括号).
DiscountDelegate discount = new DiscountDelegate(class.method);
Before going further, let's go back to our example and put the pieces together. We will add a Calculator
class to help us with the discount algorithm and give us some methods to point our delegate at.
delegate int DiscountDelegate();
class Program
{
static void Main(string[] args)
{
Calculator calc = new Calculator();
DiscountDelegate discount = null;
if (DateTime.Now.Hour < 12)
{
discount = new DiscountDelegate(calc.Morning);
}
else if (DateTime.Now.Hour < 20)
{
discount = new DiscountDelegate(calc.Afternoon);
}
else
{
discount = new DiscountDelegate(calc.Night);
}
new ShoppingCart().Process(discount);
}
}
class Calculator
{
public int Morning()
{
return 5;
}
public int Afternoon()
{
return 10;
}
public int Night()
{
return 15;
}
}
class ShoppingCart
{
public void Process(DiscountDelegate discount)
{
int magicDiscount = discount();
// ...
}
}
As you can see, we created a method in the Calculator
class for each logical branch. We created an instance of Calculator
and an instance of DiscountDelegate
in the Main
method that work together to set up the target method we want to call.
Great, now instead of having to worry about the logic in our Process
method, we simply call the delegate we were given. Remember, we don’t care how the delegate was created (or even when), we just call it like any other method when we need the value. As you can see, another way to think of a delegate is that it defers(推迟,遵守(to)) the execution of a method. The calculator method was chosen at some point in the past, but not actually executed until we called discount()
. Looking at our solution, there still seems to be a lot of ugly code. Do we need a different method for every return value in the Calculator
class? Of course, not; let's consolidate(加强,巩固) some of this mess(脏乱状态).
delegate int DiscountDelegate();
class Program
{
static void Main(string[] args)
{
new ShoppingCart().Process(new DiscountDelegate(Calculator.Calculate));
}
}
class Calculator
{
public static int Calculate()
{
int discount = 0;
if (DateTime.Now.Hour < 12)
{
discount = 5;
}
else if (DateTime.Now.Hour < 20)
{
discount = 10;
}
else
{
discount = 15;
}
return discount;
}
}
class ShoppingCart
{
public void Process(DiscountDelegate discount)
{
int magicDiscount = discount();
// ...
}
}
There we go, much better. You'll notice we cleaned things up by making the Calculate
method static and not bothering to keep a reference to the DiscountDelegate
in the Main
method. OK, so now, you know everything there is to know about delegates, right? Well, if this was 2004 and .NET 1.1, the answer would be 'yes', but fortunately, the framework has matured(成熟) since then.
……更多精彩,请参考原文
不知道这样的方式,同志们习惯不!