首页 / C# / C#学习笔记【九】——委托之一
C#学习笔记【九】——委托之一
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#学习笔记【九】——委托之一,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7589字,纯文字阅读大概需要11分钟。
内容图文
![C#学习笔记【九】——委托之一](/upload/InfoBanner/zyjiaocheng/684/cbf4dd65bce84d3a8082ad9e0312f315.jpg)
9.1委托的声明与赋值
委托(delegate)是一种存储函数引用的类型。
委托的定义指定了一个返回类型和一个参数列表(告诉编译器这个委托可以指向哪些类型的方法)。
定义了委托之后,就可以创建该委托的实例(声明该委托类型的变量),接着就可以把一个返回类型和参数列表跟委托一样的函数赋值给这个变量。
委托的使用分两步:
定义
声明(变量)
结构体,枚举的使用同上都分为定义和声明。整数类型数组类型字符串类型都是直接声明变量的,因为类型的定义已经完成了(CLR中已经完成定义)。
namespace c_sharp_001
{
//委托的定义与函数类似,区别在于:
//定义委托要加delegate关键字
//委托的定义不需要结构体
public delegate double MyDelegate(double param1, double param2);
class Program
{
//委托的定义也可也在class里
private delegate string GetAString();
static double Multiply(double param1, double param2)
{
return param1 * param2;
}
//定义一个Main方法
static void Main(string[] args)
{
MyDelegate de;//利用委托的定义声明一个变量
de = Multiply;//给一个委托变量赋值时(委托变量指向一个函数),返回值和参数列表必须一样
Console.WriteLine(de(5.0, 2.0));
int x = 10;
//GetAString getXString = new GetAString(x.ToString);//把方法名给一个委托的构造方法 //getXString指向了x中的ToString方法
GetAString getXString = x.ToString;
string s = getXString();//把方法名直接给委托的实例
//string s = getXString.Invoke();//通过Invoke方法调用getXstring所引用的方法 Console.WriteLine(s);
Console.ReadKey();
}
}
}
namespace c_sharp_practice04
{
class Program
{
static void Main(string[] args)
{
//使用委托类型作为方法的参数
PrintString method = Method1;
PrintStr(method);
method = Method2;
PrintStr(method);
Console.ReadKey();
}
private delegate void PrintString();
static void PrintStr(PrintString print)
{
print();
}
static void Method1()
{
Console.WriteLine("Method1");
}
static void Method2()
{
Console.WriteLine("Method2");
}
}
}
9.2预定义的委托类型
9.2.1Action委托
Action委托引用了一个无返回值的方法,它可以通过泛型(传递0~16个参数类型)去指定Action指向的方法的多个参数类型。
Action
Action<in T>
Action<in T1,in T2>
Action<in T1,in T2 .... inT16>
namespace c_sharp_practice04
{
class Program
{
static void PrintString()
{
Console.WriteLine("PrintString");
}
static void PrintString(string str)
{
Console.WriteLine(str);
}
static void PrintInt(int i)
{
Console.WriteLine(i);
}
static void Print(int i,int j,string str)
{
Console.WriteLine(i+j+str);
}
static void Main(string[] args)
{
Action a = PrintString;//Action是系统内置(预定义)的委托类型,它可以指向一个没有参数,没有返回 //值的方法
Action<int> b = PrintInt;//在Action后指定一个泛型,就可以指定Action委托类型所指向的方法的参数
Action<string> c = PrintString;//定义了两个PrintString方法,系统会自动寻找匹配的方法
Action<int, int, string> d=Print;
d(1, 2, "是输出的和");
Console.ReadKey();
}
}
}
9.2.2Func委托
Func引用了一个带有一个返回值的方法,它可以传递0~16个参数类型,和一个返回类型。
Func<out TResult>
Func<in T,out TResult>
Func<int T1,inT2,,,,,,in T16,out TResult>
namespace c_sharp_practice04
{
class Program
{
static int Text1()
{
return 1;
}
static int Text2(string str)
{
Console.WriteLine(str);
return 1;
}
static void Main(string[] args)
{
Func<int> a = Text1;//Func中的泛型指定的是方法的返回类型
Func<string, int> b = Text2;//Func后可以有0~16个参数类型和一个返回类型(在最后)
}
}
}
9.2.3用委托扩展冒泡排序
namespace c_sharp_practice04
{
class Employee
{
public string Name { get; private set; }
public int Salary { get; private set; }
public Employee(string name,int salary)
{
this.Name = name;
this.Salary = salary;
}
public static bool Compare(Employee e1,Employee e2)
{
if (e1.Salary > e2.Salary) return true;
return false;
}
public override string ToString()
{
return Name + ":" + Salary;
}
}
}
namespace c_sharp_practice04
{
class Program
{
//只能对一种类型的数据排序
static void Sort(int[] sortArray)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
if (sortArray[i] > sortArray[i + 1])
{
int temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
//通过委托,扩展为各类型数据通用的冒泡排序
static void CommonSort<T>(T[] sortArray,Func<T,T,bool> compareMethod)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
if (compareMethod(sortArray[i],sortArray[i+1]))
{
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
static void Main(string[] args)
{
Employee[] employees = new Employee[]
{
new Employee("asdf",120),
new Employee("wdft",999),
new Employee("qadg",345),
new Employee("ipjk",12434),
new Employee("cvnm",22),
new Employee("egyu",2324)
};
CommonSort<Employee>(employees, Employee.Compare);
foreach(var emp in employees)
{
Console.WriteLine(emp);//默认调用ToString方法
}
Console.ReadKey();
}
}
}
9.2.4多播委托
前面使用的委托都只包含一个方法的调用,但是委托也可以包含多个方法,这种委托叫做多播委托。使用多播委托就可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的(返回)结果,所以一般我们把多播委托的返回类型声明为void。
Action action1 = Test1;
action2+=Test2;
action2-=Test1;
多播委托包含一个逐个调用的委托集合,如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。
namespace c_sharp_practice04
{
class Program
{
static void Text1()
{
Console.WriteLine("Text1");
}
static void Text2()
{
Console.WriteLine("Text2");
}
static void Main(string[] args)
{
Action a = Text1;
a += Text2;//添加一个委托的引用
a();
a -= Text1;//
Console.WriteLine("-----");
a();
a -= Text2;
//a();//当一个委托没有指向任何一个方法,调用的时候出现异常null
Console.ReadKey();
}
}
}
取得多播委托中所有方法的委托。
Action a1 = Method1;
a1+=Method2;
Delegate[] delegates=a1.GetInvocationList();
foreach(delegate d in delegates){
//d();
d.DynamicInvoke(null);
}
遍历多播委托中所有的委托,然后单独调用
namespace c_sharp_practice04
{
class Program
{
static void Text1()
{
Console.WriteLine("Text1");
}
static void Text2()
{
Console.WriteLine("Text2");
}
static void Main(string[] args)
{
Action a = Text1;
a += Text2;//添加一个委托的引用
Delegate[] delegates = a.GetInvocationList();//取得多播委托中的所有委托
foreach(Delegate de in delegates)
{
de.DynamicInvoke();//遍历取得的所有委托,单独调用
}
Console.ReadKey();
}
}
}
9.2.5匿名委托
前面我们使用委托,都是先定义一个方法,然后把方法给委托的实例。但还有另外一种使用委托的方式,不用去定义一个方法,应该说是使用匿名方法(方法没有名字)。
Func<int, int, int> plus = delegate (int a, int b) {//任何使用委托变量的地方都可以用匿名方法赋值
int temp = a + b;
return temp;
};
int res = plus(34, 34);
Console.WriteLine(res);
在这里相当于直接把要引用的方法直接写在了后面,优点是减少了要编写的代码,减少代码的复杂性。多用于回调。
9.2.6Lambda表达式
可以使用Lambda表达式代替匿名方法。只要有委托参数类型的地方就可以使用Lambda表达式。9.2。5的例子可以修改为:
Func<int, int, int> plus = (arg1, arg2) =>
{
int temp = arg1 + arg2;
return temp;
};
int res = plus(34, 34);
Console.WriteLine(res);
Lambda运算符“=>”的左边列出了需要的参数,如果是一个参数可以直接写a=>(参数名自己定义),如果多个参数就使用括号括起来,参数之间以,间隔。
如果Lambda表达式的实现代码中需要多条语句,就必须添加花括号和return语句。但如果Lambda表达式只有一条语句,在方法快内就不需要花括号和return语句,编译器会自动添加return语句。
Func<double, double> square = x => x * x;
Func<double, double> square = x =>
{
return x * x;
};
通过Lambda表达式可以访问Lambda表达式块外部的变量。这是一个非常好的功能,但如果不能正确使用,也会非常危险。示例:
int somVal = 5;
Func<int, int> f = x => x + somVal;
Console.WriteLine(f(3));//8
somVal = 7;
Console.WriteLine(f(3));//10
这个方法的结果,不但受到参数的控制,还受到somVal变量的控制,结果不可控,容易出现编程问题,用的时候要谨慎。
内容总结
以上是互联网集市为您收集整理的C#学习笔记【九】——委托之一全部内容,希望文章能够帮你解决C#学习笔记【九】——委托之一所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。