委托:
把方法当作参数进行传递。委托是一个类型,这个类型可以赋值一个方法的引用。(一个方法的引用可以赋值给这个委托类型)
定义委托:<访问修饰符> delegate 返回值 委托名称(<参数列表>);
使用委托:委托名称 委托类型变量 = 静态方法名 / 委托名称 委托类型变量 = 实例方法
class Program
{
public delegate void IntMethod(int x); //定义委托
delegate string GetAString();
static void Main(string[] args)
{ //使用委托
IntMethod intMethod = null;
//委托类型可以引用其它方法,设置为null表示没有引用任何方法
intMethod = IntMethodTest;//方法当作参数传递,委托可以指向任何方法(实例方法/静态方法等)
intMethod(100000); //通过委托调用方法
//实例对象赋值方法一
int i = 123456;
GetAString getAString = i.ToString; //把方法赋值时不能加(),加()时调用它 i.ToString自身转换为字符串
//实例对象赋值方法二
GetAString getAStringy = new GetAString(y.ToString);//new GetAString()无法为空
Console.WriteLine(getAString());
}
public static void IntMethodTest(int x)
{
Console.WriteLine("IntMethod的test" + x);
}
}
IntMethod的test100000
123456
333444555
委托数组以及把委托声明的变量当作参数传递
class MathOp
{
public static double MultiplayByTwo(double value)
{
return value * 2;
}
public static double Square(double value)
{
return value * value;
}
}
//调用
public delegate double DoubleOpDelegate(double x); //可以指向返回值为double类型的方法
static void Main(string[] args)
{
//声明一个委托类型的数组
DoubleOpDelegate[] operas = { MathOp.MultiplayByTwo, MathOp.Square };
foreach(DoubleOpDelegate op in operas)//遍历数组
{
//op相当于委托类型的变量,指向数组中的每个元素
// Console.WriteLine(op(3));
ProcessAndDisplay(op, 4);
}
}
//把委托声明的变量当作参数传递
static void ProcessAndDisplay(DoubleOpDelegate op,double value)
{
double result = op(value);
Console.WriteLine("Result:" + result);
}
Result:8
Result:16
Action委托和Func委托(系统自带 )
1)Action委托:用于返回值为void类型
Action:无参数无返回值
Action<int T>:参数类型为int型,无返回值
Action<int T,int T........>:参数类型为int型,无返回值
public static void Sums(int x,double y)
{
Console.WriteLine("和:" + (x + y));
}
static void Main(string[] args)
{
Action<int, double> action = Sums;
action(2, 4.6);
}
和:6.6
2)Func委托:用于有返回值的情况
Func<int T,double T,string> :参数类型为int,double,返回值类型为string
public static String Test(int x,double y)
{
return "happy" + x + y;
}
static void Main(string[] args)
{
Func<int, double, string> f = Test;
Console.WriteLine( f(3, 1.8));
}
happy31.8
多播委托
委托可以包含多个方法的调用,这种委托叫做多播委托。使用多播委托可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的结果。返回类型为void。
class Program
{
public static void Test1()
{
Console.WriteLine("test123");
}
public static void Test2()
{
Console.WriteLine("test456");
}
static void Main(string[] args)
{
Action action = Test1;
action(); // test123
action += Test2; //此时action既指向test1又指向test2,相当于一个集合
action(); //test123 test456
//获取委托集合
Delegate[] delegates = action.GetInvocationList();
foreach(Delegate d in delegates) //遍历集合
{
d.DynamicInvoke();//动态调用里面的方法 //test123 test456
}
}
}
test123
test123
test456
test123
test456
匿名方法和Lambda表达式
1)使用委托,先定义一个方法,然后把方法给委托的实例。
2)使用委托,使用匿名方法(方法没有名字)
使用匿名方法的地方:某个方法使用到的地方很少,单独定义一个方法再赋值给一个委托的话,较为麻烦。使用匿名方法的话可以减少代码量和复杂性。
1)定义方法:
class Program
{
static void Main(string[] args)
{
Func<int, int, int> func = Sum;
int result = func(19, 3);
Console.WriteLine(result);
}
public static int Sum(int a, int b)
{
return a + b;
}
}
2)匿名方法:
class Program
{
static void Main(string[] args)
{
Func<int, int, int> func = delegate (int a, int b)
{
return a + b;
};
int result = func(20, 10);
Console.WriteLine(result);
}
}
Lambda表达式:匿名方法简写的表达式
当Lambda表达式只有一条语句的时候,可以省略括号和return语句。多行语句需要加括号和return语句。
Func<int, int, int> func = delegate (int a, int b)
{
return a + b;
};
第一步:Func<int, int, int> func = (int a, int b)
{
return a + b;
};
第二步:Func<int, int, int> func = ( a, b) => { return a + b; };
第三步:Func<int, int, int> func = ( a, b) => a + b;
只有一个参数时,不需要写括号:Func<double, double> square = x => x * x;
Lambda表达式可以访问外部变量:
int a = 5;
Func<int, int> func = x => x + a;
方法的结果,不但受到参数的控制,还受到外部变量的控制,结果不可控。
事件
“工具人的操作,下楼后可以给懒人东西。懒人把要带的东西委托给工具人,工具人在下来后调用委托。”
未加事件前:
工具人:
delegate void DownStairDelegate();
class ToolMan
{
public string name { get; private set; }
//声明委托
public DownStairDelegate downStairDelegate = null;
public ToolMan(string name)
{
this.name = name;
}
public void DownStair()
{
Console.WriteLine("工具人" + name + "下楼了");
if (downStairDelegate != null)
{
downStairDelegate();
}
}
}
懒人:
class LazyMan
{
public string name { get; private set; }
public LazyMan(string name)
{
this.name = name;
}
public void GetFood()
{
Console.WriteLine("给" + name + "取外卖");
}
public void GetPackage()
{
Console.WriteLine("给" + name + "取快递");
}
}
操作:
class Program
{
static void Main(string[] args)
{
ToolMan toolMan = new ToolMan("小明");
LazyMan lazyMan1 = new LazyMan("张三");
LazyMan lazyMan2 = new LazyMan("李四");
LazyMan lazyMan3 = new LazyMan("王五");
toolMan.downStairDelegate += lazyMan1.GetFood;
toolMan.downStairDelegate += lazyMan2.GetPackage;
toolMan.downStairDelegate += lazyMan1.GetFood;
toolMan.DownStair();
//可以在列表中减去必做项
toolMan.downStairDelegate -= lazyMan1.GetFood;
toolMan.DownStair();
//其他人可以删除原本的列表(使用事件可以解决)
toolMan.downStairDelegate = lazyMan1.GetFood;
toolMan.DownStair();
//工具人不下楼,也可以触发委托。消息发出去,但是实际上没有执行。
toolMan.downStairDelegate(); //(使用事件可以解决)
}
}
触发只能由工具人触发,不让其在外部触发。其它人无法发布消息,只能订阅消息。
解决这两个问题可以通过事件,在使用委托前添加event.
public event DownStairDelegate downStairDelegate = null;
事件是受限制的委托。
其他人在使用委托时只能 += / -= 不能使用直接赋值 = 。
事件只能在内部触发,不能在外部调用。
标签:string,委托,int,void,static,public,表达式,Lambda From: https://www.cnblogs.com/Joyce-mi7/p/16914696.html