总结:
○ 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
○ 触发委托有2种方式: 委托实例.Invoke(参数列表),委托实例(参数列表)
○ 事件可以看作是一个委托类型的变量
○ 通过+=为事件注册多个委托实例或多个方法
○ 通过-=为事件注销多个委托实例或多个方法
delegate是委托声明关键字
event是事件声明关键字
event 委托类型= 事件,可通过+=来注册同委托类型的实例方法
delegete 方法 =委托,通过=来赋值同委托类型的实例方法
○ Public delegate void EventHandler(object ob,EventArgs e);
○ EventHandler就是一个委托
public event EventHandler myEvent;
myEvent就是一个声明定义成为EventHandler类型的事件。
myEvent可以+=注册多个EventHandler类型的实例或同类型的方法。
myEvent+=new EventHandler((onject ob,EventArgs e)=>{
//方法体
});
myEvent执行一次可以全部调用所有注册过的方法或委托实例。
这里的myEvent等同于WinForm中普通Control控件的Click事件(为控件单击事件注册方法的过程与上面的形式过程相同)。
/********************************************易混淆点解析
泛型很适用于集合,我们常见的泛型集合有:List<T>,Dictionary<K,V>等等(T,K,V就代表不确定的类型,它是一种类型占位符,当然你也可以使用其他符号代替,只不过一般常规都是用T,T1,T2这种,如A,B,C,AA,BB,ABC...等等都可以,甚至一个单词或汉字也可以,因为编译器最终编译的时候会将这些占位符替换成对应的实际类型,也就是泛型要使用的实例的类型),无一不是利用的泛型这一特性,若没有泛型,我们会多出很多重载方法,以解决类型不同,但是执行逻辑相同的情况。
Action<AA, BB> myAction;//这里不能这么用,因为Action是已经被封装好的委托,只能实例化来用它(不能重新声明定义)。
event Action<object> myActionEvent2;//可以用封装好的Action定义成事件注册其他方法用。
//声明委托,其中MyT, MyA, MyB, CC就是随便自己定义的占位符
public delegate MyB MyFunction<MyT, MyA, MyB, CC>(MyT t, MyA a, MyB b, CC c);
//定义委托实例即事件
event MyFunction<int, double, object, string> MyFunctionEvent;
public void Main()
{
//为事件注册方法
MyFunctionEvent += MyFuncExcut;
}
public object MyFuncExcut(int a,double b,object c,string d)
{
return c;
}
/*******************自带封装的func因为重载中全部是有返回参数的,所以实例也必须要有返回参数
//
// 摘要:
// 封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。
//
// 类型参数:
// TResult:
// 此委托封装的方法的返回值类型。此类型参数是协变。即可以使用指定的类型或派生程度更高的类型。有关协变和逆变的更多信息,请参见泛型中的协变和逆变。
//
// 返回结果:
// 此委托封装的方法的返回值。
[TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
public delegate TResult Func<out TResult>();
其中TResult是占位符,可用任何其他字母或字符串表示;
public static Func<int> myFunc;
main()
{
//这里int只是声明返回参数类型TResult,注册的方法体中无形参
//注意:这里赋值或注册实例的时候new 后的委托类型不能带返回类型,只有尖括号中要填泛型对应的实际的类型参数,因为在声明该泛型委托的时候就已经在尖括号里将返回类型对应上了
myFunc += new Func<int>(() => { return 99; });
int res=myFunc();
}
因为封装好的Func重载函数(16个重载函数)返回泛型参数都是在尖括号的最后一位,所以使用时需要注意形参的使用顺序,否则报错。
要想自由度更高的泛型方法,就要自定义泛型委托,这样就可以把泛型的参数(尖括号中的泛型类型声明)和传入的形参和返回参数按任意顺序对应。
/****************************************************注意点
//声明委托
public delegate T MyGetValue<A,T,B>(A a,B b);
//定义委托实例(此时需要填入实际参数而不时泛型的代表某类型的占位符),注意:这里声明的时候不能带返回类型,就是在MyGetValue的前面,否则报错,自带封装好的Func委托也不能带返回类型在new 实例该Func委托的时候,只有尖括号中要填泛型对应的实际的类型参数,因为在声明该泛型委托的时候就已经在尖括号里将返回类型对应上了。
public MyGetValue<int,double,float> MyGetValueInstance;
main()
{
//委托赋值注册时new 委托类型时也要填实际的类型,跟声明此委托实例时声明的实际参数类型一一对应。注意:这里注册实例的时候new 后的委托类型不能带返回类型(MyGetValue前面),否则报错,自带封装好的Func委托也不能带返回类型在new 实例该Func委托的时候,只有尖括号中要填泛型对应的实际的类型参数,因为在声明该泛型委托的时候就已经在尖括号里将返回类型对应上了。
MyGetValueInstance = new MyGetValue<int, double, float>((int a,float c)=> { double res = a + c; return res; });
}
/********************************************泛型和object的使用区别
C#中object是一切类型的基类,可以用来表示所有类型。
而泛型是指将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。
你可以将泛型理解成替换,在使用的时候将泛型参数替换成具体的类型,这个过程是在编译的时候进行的,使用泛型编译器依然能够检测出类型错误。
而object表示其他类型是通过类型转换来完成的,而所有类型转化为object类型都是合法的,所以即使你先将object对象赋值为一个整数再赋值为一个字符串,编译器都认为是合法的。
举个例子:
object GetValue(); //object方式
T GetValue<T>(); //泛型方式
在使用的时候
int a=(int)GetValue(); //这个编译的时候没问题的,但是如果GetValue返回的是其他类型,运行的时候就会出错
int a=GetValue<int>(); //这样无论如何都不会出错的,因为泛型被指定为int,它就一定会返回int,如果是其他类型,编译过程就会报错
/**********************************************
一、简介
简单记录一下C#中泛型类,泛型方法,泛型委托等泛型的使用,从.NetFramework2.0开始,支持泛型,通过反编译可以看到使用泛型的地方,都是使用了占位符 `1,当运行的时候,会将占位符替换成对应的类型
二、泛型方法
泛型方法就是为了解决不同类型要使用同样方法的问题,泛型方法需要在方法名的后面带一个<T>,T是类型参数,只是一个占位符,也可以用别的名字代替
泛型(Generic),是将不确定的类型预先定义下来的一种C#高级语法,我们在使用一个类,接口或者方法前,不知道用户将来传什么类型,或者我们写的类,接口或方法相同的代码可以服务不同的类型,就可以定义为泛型。这会大大简化我们的代码结构,同时让后期维护变得容易。
泛型很适用于集合,我们常见的泛型集合有:List<T>,Dictionary<K,V>等等(T,K,V就代表不确定的类型,它是一种类型占位符,当然你也可以使用其他符号代替,只不过一般常规都是用T,T1,T2这种,如A,B,C,AA,BB,ABC...等等都可以,甚至一个单词或汉字也可以,因为编译器最终编译的时候会将这些占位符替换成对应的实际类型,也就是泛型要使用的实例的类型),无一不是利用的泛型这一特性,若没有泛型,我们会多出很多重载方法,以解决类型不同,但是执行逻辑相同的情况。
看看上面这一堆介绍看着都想睡觉了,没办法,CSDN要求文字个数不够就不给推荐,估计这些简介也没几个人会去仔细看的哈,哈哈哈。
废话一大堆,那么泛型到底长啥样?,看到下面代码中的 “T” 没有,那就是泛型。
namespace 泛型
{
class Program
{
static void Main(string[] args)
{
Test<string>();
Console.ReadKey();
}
static void Test<T>()
{
Console.WriteLine(typeof(T).FullName);
}
}
}
输出:System.String
/实例演示******************************************************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LambdaTest
{
public class LambdaCreate
{
//自定义委托(Action和Func实质上是封装好的委托)
//将委托封装成事件来注册,则可以一个事件注册多个同类型方法(事件执行将调用全部已注册过的方法)
delegate void delegate_action1();
event delegate_action1 delegate_action1_event;
delegate void delegate_action2(object a,object b);
event delegate_action2 delegate_action2_event;
delegate object delegate_func1(object a);
event delegate_func1 delegate_func1_event;
delegate object delegate_func2(object a,object b);
event delegate_func2 delegate_func2_event;
//Action和Func实质上是封装好的委托
//自定义泛型委托(多写几个重载的话可替代Action和Func)
delegate void delegate_func3<T>(T a, T b);
delegate T delegate_func4<T>(T a, T b);
public void Test()
{
//除事件外,被定义封装的委托可当成参数传递使用
//有16个函数重载,最多的有16个形参
Action action1 = () => { int c = 8 + 9; };
Action<int, int> action2 = (int a, int b) => { int c = a + b; };
Action<object, object> action3 = (object a, object b) => { a = b; };
//有16个函数重载,最多的有16个形参
Func<int> func1 = () => { int c = 1; return c; };//Fun至少要有一个返回参数,输入形参可没有
Func<int, int> func2 = (int a) => { int c = a; return c; };
Func<object, object> func3 = (object a) => { object c = a; return c; };//最后一个形参是返回类型
//自定义委托,可替代Action和Func(Action和Func实质上是封装好的委托)
delegate_action1_event += new delegate_action1(() => { int c = 8 + 9; });
delegate_action2_event += new delegate_action2((object a,object b) => { object c = a; c = b; });
delegate_func1_event += new delegate_func1((object a) => { object c = 9;return c; });
delegate_func2_event += new delegate_func2((object a,object b) => { object c = a; return c; });
//以上部分方法的lambda表达式写法
action1 = new Action(() => { int c = 8 + 9; });
action3 = new Action<object,object>((object a, object b) => { a = b; });
func1 = new Func<int>(()=> { int c = 1; return c; }) ;
func3 = new Func<object, object>((object a) => { object c = a; return c; });
delegate_action1 normal_delegate_action1 = new delegate_action1(() => { int a = 9; });
delegate_action2 normal_delegate_action2 = new delegate_action2((object a,object b) => { a = b; });
delegate_func1 normal_delegate_func1 = new delegate_func1((object a) => { object c = a; return c; });
delegate_func2 normal_delegate_func2 = new delegate_func2((object a,object b) => { object c = a; return b; });
normal_delegate_action1 = () => { int a = 9; };
normal_delegate_action2 = (object a, object b) => { a = b; };
normal_delegate_func1 = (object a) => { object c = a; return c; };
normal_delegate_func2 = (object a, object b) => { object c = a; return b; };
delegate_action1_event += () => { int c = 8 + 9; };
delegate_action2_event += (object a, object b) => { object c = a; c = b; };
delegate_func1_event += (object a) => { object c = 9; return c; };
delegate_func2_event += (object a, object b) => { object c = a; return c; };
//泛型声明的时候是T,定义实例的时候需要填具体的参数类型(而不是T或T1,T2)
delegate_func3<int> normal_delegate_func3 = new delegate_func3<int>((int a,int b) => { int c = a + b; });
delegate_func4<object> normal_delegate_func4 = new delegate_func4<object>((object a, object b) => { object c = a; return b; });
}
//************************************ 泛型方法声明定义及使用
public T GetForm<T>(string formName) where T : Form
{
T res = default(T);
foreach (Form form in Application.OpenForms)
{
if (form.Name == formName)
{
form.Invoke(new Action(() =>
{
res = form as T;
}));
break;
}
}
return res;
}
public T GetForm<T,T1,T2,T3>(string formName,T1 t1,T2 t2,T3 t3) where T :Form
{
T res = default(T);
foreach (Form form in Application.OpenForms)
{
if (form.Name == formName)
{
form.Invoke(new Action(() =>
{
res = form as T;
}));
break;
}
}
object a1 = t1 as object;
object a2 = t2 as object;
object a3 = t3 as object;
string a4 = t1 as string;
Form a5 = t2 as Form;
int a6 = Convert.ToInt32(t3);
return res;
}
public T GetValue<T,T1,T2>(T1 t1,T2 t2) where T:new()
{
double res = 0;
res += Convert.ToInt32(t1);
res += Convert.ToInt32(t2);
T t = new T();
return t;
}
public T GetValue<T>(T a1,T a2) where T :class, new()
{
double res = Convert.ToInt32(a1) + Convert.ToInt32(a2);
T resValue = res as T;
return resValue;
}
public double GetValue2<T>(T a1, T a2)
{
double res = Convert.ToInt32(a1) + Convert.ToInt32(a2);
return res ;
}
public void Test2()
{
Form form1 = this.GetForm<Form>("MainForm");
Form form2 = this.GetForm<Form,object,int,double>("MainForm",new object(),int.MaxValue,double.MaxValue);
object c = GetValue<object, double, int>( 8, 9);
object res=GetValue<object>(2,3);
double res2 = GetValue2<double>(2.0, 3.0);
double res3 = GetValue2<int>(2, 3);
}
Action<AA, BB> myAction;//这里不能这么用,因为Action是已经被封装好的委托,只能实例化来用它(不能重新声明定义)。
event Action<object> myActionEvent2;//可以用封装好的Action定义成事件注册其他方法用。
//声明委托
public delegate MyB MyFunction<MyT, MyA, MyB, CC>(MyT t, MyA a, MyB b, CC c);
//定义委托实例即事件
event MyFunction<int, double, object, string> MyFunctionEvent;
public static Func<int> myFunc;
//声明委托
public delegate T MyGetValue<A,T,B>(A a,B b);
//定义委托实例(此时需要填入实际参数而不时泛型的代表某类型的占位符),注意:这里声明的时候可以不用带返回类型
public MyGetValue<int,double,float> MyGetValueInstance;
public void Main()
{
//委托赋值注册时new 委托类型时也要填实际的类型,跟声明此委托实例时声明的实际参数类型一一对应。注意:这里注册实例的时候new 后的委托类型可以不用带返回类型
MyGetValueInstance = new MyGetValue<int, double, float>((int a,float c)=> { double res = a + c; return res; });
myFunc = new Func<int>(() => { return 99; });
//为事件注册方法
MyFunctionEvent += MyFuncExcut;
}
public object MyFuncExcut(int a,double b,object c,string d)
{
return c;
}
}
}
泛型方法比一般方法代码重用性高且简洁,因为传入参数是动态的,使用时传入类型即可。
下面为定义泛型方法例子:
public T GetInfo<T>(string s) where T:Test,new()
{
T l=new T();
return l;
}
其中where子句为可选约束语句,T:后面的Test为指定类型,new ():函数主体要使用T类型实例化时必须加此参数,否则编译不通过
使用泛型方法:
Test t = GetInfo<Test>("teststr");
/*******************************************
public delegate void Action<in T>(T obj);
}
//上面是自带封装好的Action,除其他重载的外这个参数形式是固定的
//使用实例时必须要有参数
Action<object> actionEvent = null;
actionEvent += new Action<object>((object ob) => { int res = 0; });
actionEvent(new object());
无参数的话会报错如下
//可以这样改造
//类主体中声明
delegate void myDelegate<T>(); //方法中定义
myDelegate<object> actionEvent = new myDelegate<object>(() => { int res = 0; });
actionEvent();
这样就可以使用一个带T泛型但无参数的泛型委托了,类似与Action<T>的封装但是可以不带T类型的参数调用
/**********************************************备注实例演示*****************************
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace LambdaTest
{
public class LambdaCreate
{
//自定义委托(Action和Func实质上是封装好的委托)
//将委托封装成事件来注册,则可以一个事件注册多个同类型方法(事件执行将调用全部已注册过的方法)
delegate void delegate_action1();
event delegate_action1 delegate_action1_event;
delegate void delegate_action2(object a,object b);
event delegate_action2 delegate_action2_event;
delegate object delegate_func1(object a);
event delegate_func1 delegate_func1_event;
delegate object delegate_func2(object a,object b);
event delegate_func2 delegate_func2_event;
//Action和Func实质上是封装好的委托
//自定义泛型委托(多写几个重载的话可替代Action和Func)
delegate void delegate_func3<T>(T a, T b);
delegate T delegate_func4<T>(T a, T b);
public void Test()
{
//除事件外,被定义封装的委托可当成参数传递使用
//有16个函数重载,最多的有16个形参
Action action1 = () => { int c = 8 + 9; };
Action<int, int> action2 = (int a, int b) => { int c = a + b; };
Action<object, object> action3 = (object a, object b) => { a = b; };
//有16个函数重载,最多的有16个形参
Func<int> func1 = () => { int c = 1; return c; };//Fun至少要有一个返回参数,输入形参可没有
Func<int, int> func2 = (int a) => { int c = a; return c; };
Func<object, object> func3 = (object a) => { object c = a; return c; };//最后一个形参是返回类型
//自定义委托,可替代Action和Func(Action和Func实质上是封装好的委托)
delegate_action1_event += new delegate_action1(() => { int c = 8 + 9; });
delegate_action2_event += new delegate_action2((object a,object b) => { object c = a; c = b; });
delegate_func1_event += new delegate_func1((object a) => { object c = 9;return c; });
delegate_func2_event += new delegate_func2((object a,object b) => { object c = a; return c; });
//以上部分方法的lambda表达式写法
action1 = new Action(() => { int c = 8 + 9; });
action3 = new Action<object,object>((object a, object b) => { a = b; });
func1 = new Func<int>(()=> { int c = 1; return c; }) ;
func3 = new Func<object, object>((object a) => { object c = a; return c; });
delegate_action1 normal_delegate_action1 = new delegate_action1(() => { int a = 9; });
delegate_action2 normal_delegate_action2 = new delegate_action2((object a,object b) => { a = b; });
delegate_func1 normal_delegate_func1 = new delegate_func1((object a) => { object c = a; return c; });
delegate_func2 normal_delegate_func2 = new delegate_func2((object a,object b) => { object c = a; return b; });
normal_delegate_action1 = () => { int a = 9; };
normal_delegate_action2 = (object a, object b) => { a = b; };
normal_delegate_func1 = (object a) => { object c = a; return c; };
normal_delegate_func2 = (object a, object b) => { object c = a; return b; };
delegate_action1_event += () => { int c = 8 + 9; };
delegate_action2_event += (object a, object b) => { object c = a; c = b; };
delegate_func1_event += (object a) => { object c = 9; return c; };
delegate_func2_event += (object a, object b) => { object c = a; return c; };
//泛型声明的时候是T,定义实例的时候需要填具体的参数类型(而不是T或T1,T2)
delegate_func3<int> normal_delegate_func3 = new delegate_func3<int>((int a,int b) => { int c = a + b; });
delegate_func4<object> normal_delegate_func4 = new delegate_func4<object>((object a, object b) => { object c = a; return b; });
}
//************************************ 泛型方法声明定义及使用
public T GetForm<T>(string formName) where T : Form
{
T res = default(T);
foreach (Form form in Application.OpenForms)
{
if (form.Name == formName)
{
form.Invoke(new Action(() =>
{
res = form as T;
}));
break;
}
}
return res;
}
public T GetForm<T,T1,T2,T3>(string formName,T1 t1,T2 t2,T3 t3) where T :Form
{
T res = default(T);
foreach (Form form in Application.OpenForms)
{
if (form.Name == formName)
{
form.Invoke(new Action(() =>
{
res = form as T;
}));
break;
}
}
object a1 = t1 as object;
object a2 = t2 as object;
object a3 = t3 as object;
string a4 = t1 as string;
Form a5 = t2 as Form;
int a6 = Convert.ToInt32(t3);
return res;
}
public T GetValue<T,T1,T2>(T1 t1,T2 t2) where T:new()
{
double res = 0;
res += Convert.ToInt32(t1);
res += Convert.ToInt32(t2);
T t = new T();
return t;
}
public T GetValue<T>(T a1,T a2) where T :class, new()
{
double res = Convert.ToInt32(a1) + Convert.ToInt32(a2);
T resValue = res as T;
return resValue;
}
public double GetValue2<T>(T a1, T a2)
{
double res = Convert.ToInt32(a1) + Convert.ToInt32(a2);
return res ;
}
public void Test2()
{
Form form1 = this.GetForm<Form>("MainForm");
Form form2 = this.GetForm<Form,object,int,double>("MainForm",new object(),int.MaxValue,double.MaxValue);
object c = GetValue<object, double, int>( 8, 9);
object res=GetValue<object>(2,3);
double res2 = GetValue2<double>(2.0, 3.0);
double res3 = GetValue2<int>(2, 3);
}
Action<AA, BB> myAction;//这里不能这么用,因为Action是已经被封装好的委托,只能实例化来用它(不能重新声明定义)。
event Action<object> myActionEvent2;//可以用封装好的Action定义成事件注册其他方法用。
//声明委托
public delegate MyB MyFunction<MyT, MyA, MyB, CC>(MyT t, MyA a, MyB b, CC c);
//定义委托实例即事件
event MyFunction<int, double, object, string> MyFunctionEvent;
public static Func<int> myFunc;
//声明委托
public delegate T MyGetValue<A,T,B>(A a,B b);
//定义委托实例(此时需要填入实际参数而不时泛型的代表某类型的占位符),注意:这里声明的时候可以不用带返回类型
public MyGetValue<int,double,float> MyGetValueInstance;
public void Main()
{
//委托赋值注册时new 委托类型时也要填实际的类型,跟声明此委托实例时声明的实际参数类型一一对应。注意:这里注册实例的时候new 后的委托类型可以不用带返回类型
MyGetValueInstance = new MyGetValue<int, double, float>((int a,float c)=> { double res = a + c; return res; });
myFunc = new Func<int>(() => { return 99; });
//为事件注册方法
MyFunctionEvent += MyFuncExcut;
}
public object MyFuncExcut(int a,double b,object c,string d)
{
return c;
}
}
}
泛型方法比一般方法代码重用性高且简洁,因为传入参数是动态的,使用时传入类型即可。
下面为定义泛型方法例子:
public T GetInfo<T>(string s) where T:Test,new()
{
T l=new T();
return l;
}
其中where子句为可选约束语句,T:后面的Test为指定类型,new ():函数主体要使用T类型实例化时必须加此参数,否则编译不通过
使用泛型方法:
Test t = GetInfo<Test>("teststr");