可以认为委托是持有一个或多个方法的对象,此对象可以执行它所“持有”的方法。
delegate void Del(int value);
class Program
{
static int a = 1;
static void Up(int v)
{
Console.WriteLine($"{a + v}");
}
static void Down(int v)
{
Console.WriteLine($"{a - v}");
}
static void Main()
{
Del del1 = new Del(Up);
Del del2 = new Del(Down);
del1(1);
del2(1);
Console.ReadKey();
}
output
2
0
使用委托与类的比较,入下图:
可以把委托看作是包含有序方法列表的对象,这些方法具有相同的签名和返回类型:
委托类型定义了委托对象调用列表中允许的方法的形式,如下示例代码声明了委托类型:
delegate void MyDel( int x ); // delegate为关键字,void为返回类型,MyDel为委托类型名,int为签名
委托声明与方法声明的不同:
委托类型的变量声明如下:
MyDel delVar;
有两种创建委托对象的方式,第一种是使用new运算符, new运算符的操作数组成如下:
delVar = new MyDel(Class1.Method1);
还可以使用以下快捷语法创建委托对象:
delVar = Class1.Method1;
由于委托时引用类型,可以通过赋值来改变包含在委托变量中的引用,旧的委托对象会被垃圾回收器回收。
MyDel delVar;
delVar = Class1.Method1;
delVar = Class1.Method2; // Class1.Method1将会被GC
委托可以调用额外的运算符来“组合”。
MyDel delA = Class1.Method1;
MyDel delB = Class1.Method2;
MyDel delC = delA + delB; // 组合调用列表
使用+=运算符为委托添加方法:
MyDel delA = Class1.Method1; // 创建并初始化
delA = Class2.Method2; // 增加方法
delA = StaticClass.StaticMethod; // 增加方法
由于委托是不可变的,所以每添加一个方法其实是创建了一个新的委托。 使用-=运算符为委托移除方法:
delA -= Class2.Method2; // 从委托移除方法
移除一个方法同样是创建了一个新的委托。 移除委托时的注意事项:
可以向调用方法一样简单的调用委托。
Mydel delVar = inst.MyM1;
delVar += SCl.m3;
delVar += X.Act;
...
delVar(55);
在使用参数调用委托时会使用相同的参数值(如55)。
delegate void PrintFunction();
class Test
{
public void Print1()
{
Console.WriteLine("Print1 -- instance");
}
public static void Print2()
{
Console.WriteLine("Print2 -- static");
}
}
class Program
{
static void Main()
{
Test t = new Test();
PrintFunction pf = t.Print1;
pf += Test.Print2;
pf += t.Print1;
pf += Test.Print2;
if(null!=pf)
{
pf();
}
else
{
Console.WriteLine("Delegate is empty");
}
Console.ReadKey();
}
}
output
Print1 -- instance
Print2 -- static
Print1 -- instance
Print2 -- static
delegate int MyDel();
class MyClass
{
int value = 5;
public int Add2()
{
value += 2;
return value;
}
public int Add3()
{
value += 3;
return value;
}
}
class Program
{
static void Main()
{
MyClass mc = new MyClass();
MyDel md = mc.Add2;
md += mc.Add3;
md += mc.Add2;
Console.WriteLine($"value = {md()}");
Console.ReadKey();
}
}
output
value = 12
最后一个方法执行的返回值是委托的返回值。
在调用委托列表中的下一个方法时,参数的新值回传给下一个方法
delegate void MyDel(ref int x);
class MyClass
{
public void Add2(ref int x) { x += 2; }
public void Add3(ref int x) { x += 3; }
static void Main()
{
MyClass mc = new MyClass();
MyDel md = mc.Add2;
md += mc.Add3;
md += mc.Add2;
int x = 5;
md(ref x);
Console.WriteLine($"value = {x}");
Console.ReadKey();
}
}
output
value = 12
匿名方法是在初始化委托时内联声明的方法。
匿名方法表达式的语法包含以下组成部分:
delegate ( Parameters ) { ImplementationCode }
若委托的返回类型为int,则匿名方法中也应返回int。
delegate int Del(int n);
static void Main()
{
Del d = delegate(int x) { return x + 20; } // 返回一个整型值
}
除了数组参数,匿名方法的参数列表必须与委托有以下匹配:
delegate void Del(int x);
Del d = delegate
{
PrintMessage();
CleanUp();
};
如果委托声明的参数列表包含params参数,那么匿名方法的参数列表将忽略params关键字:
delegate void Del(int x, params in[] y);
Del d = delegate(int x, int[] y){...};
delegate void MyDel(int x, params int[] y);
class MyClass
{
static void Main()
{
MyDel md = delegate (int x, int[] y)
{
foreach(var i in y)
{
Console.WriteLine(i);
}
};
md(1, 2, 3, 4);
Console.ReadKey();
}
}
output
2
3
4
使用Lambda表达式创建委托:
MyDel del = delegate(int x) {return x + 1;}; // 匿名方法
MyDel newdel = (int x) => {return x + 1;}; // Lambda表达式
Lambda表达式的简化规则:
(参数,参数) (参数) 参数 () | => | {语句} 表达式 |
---|
Lambda表达式的语法由Lambda运算符和左边的参数部分以及右边的Lambda主体构成。
Action<>委托可以拥有n个参数(0-16),无返回值。
class Program
{
static void Method1()
{
Console.WriteLine("without any parameter");
}
static void Method2(int i)
{
Console.WriteLine($"the int is {i}");
}
static void Method3(string s, double d)
{
Console.WriteLine($"the string is {s}, the double is {d}");
}
static void Main()
{
Action A1 = Method1;
Action<int> A2 = Method2;
Action<string, double> A3 = Method3;
A1();
A2(1);
A3("hello", 3.14);
Console.ReadKey();
}
}
output
without any parameter
the int is 1
the string is hello, the double is 3.14
Func<>委托可以拥有n个参数(1-16),类型参数中的最后一个作为返回值类型。因此类型参数不能为空,至少有一个返回类型。
class Program
{
static int Method1(int i)
{
return i * 10;
}
static string Method2(int a, double d)
{
return (a + d).ToString();
}
static void Main()
{
Func<int, int> F1 = Method1;
Func<int, double, string> F2 = Method2;
Console.WriteLine($"{F1(10)}");
Console.WriteLine($"{F2(1, 3.14)}");
Console.ReadKey();
}
}
output
100
4.14
Predicate<>委托拥有一个参数,其返回值为bool型。
class Program
{
static bool Method(int i)
{
return i > 0 ? true : false;
}
static void Main()
{
Predicate<int> P = Method;
Console.WriteLine(P(10));
Console.ReadKey();
}
}
output
True
通过匿名方法使用Predicate<>,
class Program
{
static void Main()
{
var anomynous = new Predicate<int>(delegate (int i) { return i > 0 ? true : false; });
Console.WriteLine(anomynous(1));
Console.ReadKey();
}
}
output
True
原文:https://www.cnblogs.com/jizhiqiliao/p/10649160.html