Delegates
The concept of delegates is a very powerful feature in many programming languages,including C#.
Delegates的概念在许多编程语言中是强大的特性,包括C#.
I believe that the discussion of advanced programming in C# cannot start without delegates.
我相信对C#高级功能的讨论,delegates是你必须要首先阐述的。
In this chapter, you learn about delegates and why they are essential.
在这一章,你会学习delegates,并且明白他们为啥是essential(基本的)
Let's recall the fundamentals of class and object.
让我们回忆一下class 和 object的基础知识。
To create an object—let's say, obA from a class A, you can write something like the following.
创建一个object,例如 从类A中实例化一个obA,你可以写下如下:
A obA=new A();
Here, the object reference obA points to an object of A.
Similar to this, delegates are reference types, but the key difference is that they point to methods.
于此相似,delegates是引用类型的,但是关键的差异是delegates指向的是方法。
Simply put,a delegate is an object that knows how to invoke a method.
相似地,
A delegate derives from System.Delegate class.
委托delegates 从System.Delegate派生的。
Let's look at it from another point of view.
You know what a variable is and how it behaves. You have seen that you can put different boolean values (true/false), strings (or, words), numbers (integer, double, etc.) in respective types of variables. But when you use delegates, you can assign a method to a variable and pass it around.
In short, by using delegates, you can treat your methods like objects. So, you can store a delegate in a variable, pass it as method parameter, and return it from a method.
The use of delegates can help promote type-safety. (In a broad sense, the term typesafety simply tells you that you cannot assign one type to another type if they are not compatible. The check for type-safety may appear both at compile time and runtime).
This is why delegates are often referred to as type-safe function pointers
为什么说delegates是类型安全的,type-safe function pointer 类型安全指针,其实就是规避了指针乱指的问题,因为C++里面函数指针不保证类型的。
Int string之类的可以切换的。C#的delegates 委托,进一步改进了一下,只能同一个类型。
Delegate is a type, similar to function pointers in C/C++.
Delegate 是一个类型,和C/C++的函数指针类似。
It stores the reference of a method inside a delegate object, to invoke the referenced method anywhere in the code.
在delegate对象内部,Delegate 储存了方法(函数)的引用(reference),并且可以在代码的任何位置,invoke 这个引用。
It also allows the method to be passed as an argument of another method.
委托也允许方法传递另外一个方法的一个参数
Unlike function pointers in C++, delegates are type-safe function pointers.
和C++函数指针不同的是,delegates是类型安全的函数指针
Delegate declaration determines a type that can refer to a method, which has the same set of arguments and returns a type.
A single delegate object can hold the reference of multiple methods that can be called on a single event.
using System;
class Program
{
//declare a delegate 声明一个委托
public delegate void delegateName(string msg);
// Declare a method with the same signature as the delegate. 声明一个方法和委托相同的签名
static void display(string msg)
{
Console.WriteLine(msg);
}
static void Main(string[] args)
{
// Create an instance of the delegate 新建并实例化一个委托
delegateName del = new delegateName(display);
//Calling the delegate call这个委托
del("Ali Asad");
}
}
• new delegateName(display); pass "display" method's reference in the delegateName constructor.
• del("Ali Asad"); call "del" which invokes the "display" method.
MultiCast 这个单词怎么翻译?
using System;
//declare a delegate 声明一个delegate
public delegate void delegateName(string msg);
class MyClass
{
// Declare a method with the same signature as the delegate.
// 声明一个方法,和delegates相同的签名
static void display(string msg)
{
Console.WriteLine("display: {0}", msg);
}
static void show(string msg)
{
Console.WriteLine("show: {0}", msg);
}
static void screen(string msg)
{
Console.WriteLine("screen: {0}", msg);
}
static void Main(string[] args)
{
delegateName del = display;
//Multicast delegate 多播委托
del += show;
del += screen;
//calling delegate 调用委托
del("Ali");
del.Invoke("你妈逼!");
}
}
using System;
//declare a delegate 声明一个delegate
public delegate void delegateName(string msg);
class MyClass
{
// Declare a method with the same signature as the delegate.
// 声明一个方法,和delegates相同的签名
static void display(string msg)
{
Console.WriteLine("display: {0}", msg);
}
static void show(string msg)
{
Console.WriteLine("show: {0}", msg);
}
static void screen(string msg)
{
Console.WriteLine("screen: {0}", msg);
}
static void Main(string[] args)
{
delegateName del = display;
//Multicast delegate 多播委托
del += show;
del += screen;
//calling delegate 调用委托
del("Ali");
del.Invoke("你妈逼!");
Console.WriteLine("================================================");
//remove method's reference
del -= show;
del("你妈逼我删了show");
}
}
Listing 5-6. Loop over each method by using getinvocationlist method
using System;
//declare a delegate 声明一个delegate
public delegate void delegateName(string msg);
class MyClass
{
// Declare a method with the same signature as the delegate.
// 声明一个方法,和delegates相同的签名
static void display(string msg)
{
Console.WriteLine("display: {0}", msg);
}
static void show(string msg)
{
Console.WriteLine("show: {0}", msg);
}
static void screen(string msg)
{
Console.WriteLine("screen: {0}", msg);
}
static void Main(string[] args)
{
delegateName del = display;
//Multicast delegate 多播委托
del += show;
del += screen;
//calling delegate 调用委托
del("Ali");
del.Invoke("你妈逼");
Console.WriteLine("================================================");
//remove method's reference
del -= show;
del("你妈逼我删了show");
Console.WriteLine("================================================");
foreach (delegateName item in del.GetInvocationList())
{
//invoke each method, and display return value
item("妈了个逼丫");
}
}
}
del.GetInvocationList(); returns a list of all referenced methods stored in "del"
内置委托
First parameter in func<> determines the method return type and the remaining are considered as a list of the argument type of method.
using System;
//declare a delegate
//public delegate void Action();
public delegate void Func();
class MyClass
{
// Declare a method with the same signature as the delegate.
//
static int Add(int x, int y)
{
Console.Write("{0} + {1} = ", x, y);
return (x + y);
}
static int Min(int x, int y)
{
Console.Write("{0} - {1} = ", x, y);
return (x - y);
}
static int Mul(int x, int y)
{
Console.Write("{0} * {1} = ", x, y);
return (x * y);
}
static string Name()
{
Console.Write("My name is = ");
return "Ali Asad";
}
static string DynamicName(string name)
{
Console.Write("My name is = ");
return name;
}
static void Main(string[] args)
{
//return string value
Func<string> info = Name;
Console.WriteLine(info());
//return string, and take string as parameter
Func<string, string> dynamicInfo = DynamicName;
Console.WriteLine(dynamicInfo("Hamza Ali"));
//return int, and take two int as parameter
Func<int, int, int> calculate = Add;
calculate += Min;
calculate += Mul;
foreach (Func<int, int, int> item in calculate.GetInvocationList())
{
Console.WriteLine(item(10, 5));
}
}
}
翻译的都是垃圾!什么逆变协变。。。唉,其实计算机行业的狂妄自大已经是由来已久的了。
using System;
class Parent{}
class Child: Parent{}
delegate Parent CovarianceHandle();
class Program
{
static Child CovarianceMethod(){
Console.WriteLine("Covariance Method");
return new Child();
}
static void Main(string[] args){
//Covariance
CovarianceHandle del = CovarianceMethod;
del();
}
}
Covariance 协变指的是 子类 继承了 父类 可以调用父类的东西(大致这个意思)
using System;
class Parent { }
class Child : Parent { }
delegate void ContravarianceHandle(Child c);
class Program
{
static void ContravarianceMethod(Parent p)
{
Child ch = p as Child;
Console.WriteLine("Contravariance Method");
}
static void Main(string[] args)
{
ContravarianceHandle del = ContravarianceMethod;
Child child = new Child();
//Contravariance
del(child);
}
}
逆变 Contravariance
Problems with Delegate
Delegates的问题
Delegates have a few problems which events have overcome. These problems are:
1. Anyone can use an assignment operator which may overwrite the references of
methods.
任何人都可以分配操作符能覆盖引用
Listing 5-13. Overwrite the references of methods in Delegate
using System;
public delegate void Action();
class Program
{
static void Display()
{
Console.WriteLine("Display");
}
static void Show()
{
Console.WriteLine("Show");
}
static void Main(string[] args)
{
Action act = Display;
act += Show;
act = Display;
act();
}
}
2. Delegate can be called anywhere in code, which may break the rule of
Encapsulation.
委托会被任何位置的代码调用,破坏了封装,
using System;
class Program
{
static void Main(string[] args)
{
//Anonymous method that doesn't return value
Action act = delegate ()
{
Console.WriteLine("Inside Anonymous method");
};
//Anonymous method that does return value
Func<int, int> func = delegate (int num)
{
Console.Write("Inside Func: ");
return (num * 2);
};
act();
Console.WriteLine(func(4));
}
}
using System;
class Program
{
static void Main(string[] args)
{
//Lambda Expression that doesn't return value
Action act = () =>
{
Console.WriteLine("Inside Lambda Expression");
};
//Lambda Expression that does have return value
Func<int, int> func = (int num) =>
{
Console.Write("Inside Func: ");
return (num * 2);
};
act();
Console.WriteLine(func(4));
}
}
using System;
delegate void MyDel(int value);//声明委托类型
class Program{
static void Main(){
Program program = new Program();
MyDel del; //声明委托变量
//创建随机整数生成器对象,并得到0到99之间的一个随机数
Random rand = new Random();
int randomValue = rand.Next(99);
//创建一个包含PrintLow和PrintHigh的委托对象并将其赋值给del变量
del = randomValue < 50 ? new MyDel(program.PrintLow):new MyDel(program.PrintHigh);
del(randomValue);//执行委托
}
void PrintLow(int value){
Console.WriteLine($"{value}-低值");
}
void PrintHigh(int value){
Console.WriteLine($"{value}-高值");
}
}
- 声明委托类型
关键词 delegate
委托声明就是函数指针,就是需要有返回值,参数签名,signature
没有方法主体的
- 创建委托对象
Mydel delVar;
组合委托:
Although the term combining delegates might give the impression that the operand delegates are
modified, they are not changed at all. In fact, delegates are immutable. After a delegate object is created,
it cannot be changed
Immutable 不可改变的。
为委托添加方法
委托虽然不可变,但是可以用+=这样的运算符。
从委托移除方法: