delegate
delegate委托,简而言之就是方法签名(类似于c++中的函数指针,相对封装性好),是引用类型。下面是委托的声明:
public delegate void TestDelegate(string message);
public delegate int TestDelegate(MyType m, long num);
可以看到类似方法的定义,但是没有方法体,定义前加上delegate关键字,可以认为是定义一个新类,所以在类的外部或者内部都行。在这里,还要介绍下Action<T>和Func<T>两种泛型委托。Action<in T1, in T2>表示一个调用两个参数(T1,T2)的无返回类型的委托。Func<in T, out TResult>表示一个带返回类型的含一个参数的委托,通常最后一个是返回类型。
Action<double> testDelegate1;//等同于delegate void testDelegate1(double param);
Func<double,double>testDelegate2;//等同于delegate double testDelegate2(double param);
下面我们来看看如何使用委托,上代码:
private delegate string GetAString();
static void Main(string[] args)
{
int x = 40;
GetAString gs = new GetAString(x.ToString);
Console.WriteLine("string is {0} ", gs());
}
//output:
//string is 40
委托还有两种使用方式,匿名方法和Lambda表达式(其实就是匿名方法,C#3.0以后用Lambda代替匿名方法),上述代码也可以改成如下代码:
GetAString gs2= delegate()
{
return x.ToString();
};//匿名方法实例化委托
GetAString gs3 = () => x.ToString();//Lambda表示是实例化委托
这样的效果都是一样的,这里说明下Lambda表达式的用法:(参数类型1 参数名1,参数类型2 参数2 ...)=> 单条语句 或者 {方法体花括号适用于多条语句 };
上面的截图转载的,很好的说明了Lambda表达式的进化。看来看去,会不会觉得委托的作用不是很大,是可以替代的,在下面的这个例子你会看到它的大用处。我们以前(学生时代)写的冒泡排序只针对基本类型的排序,对于对象的排序似乎捉襟见肘,不能直接用比较符号〈,假如我们将比较方法当作参数传入冒泡排序,不就可以了吗?这会体现了委托在泛型编程当中的作用,看代码:
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Employee[] ems ={
new Employee("Issac",2200),
new Employee("TrisD",2000),
new Employee("Wz",10000),
new Employee("Abc",4000)
};
BubbleSorter.Sort(ems, Employee.CompareSalary);
foreach (var item in ems)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
}
class Employee
{
public string Name { get; private set; }
public decimal Salary { get; private set; }
public Employee(string name,decimal salary)
{
this.Name=name;
this.Salary=salary;
}
public override string ToString()
{
return string.Format("{0},{1:C}",Name,Salary);
}
public static bool CompareSalary(Employee e1, Employee e2)
{
return e1.Salary < e2.Salary;
}
}
class BubbleSorter
{
static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Count-1; i++)
{
if (comparison(sortArray[i+1] , sortArray[i]))
{
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
}
}
// output:
//TrisD,$2,000.00
//Issac,$2,200.00
//Abc,$4,000.00
//Wz,$10,000.00
这样就实现了,传递方法泛型编程的效果。这只是简单的介绍,还有多播委托,事件就是一种特殊型的多播委托,支持 + - = 之类的运算,那就不多说了。
event
event 基于delegate,提供一种发布订阅机制, 声明方式如下:
public delegate void SampleEventHandler(object sender, EventArgs e);
public event SampleEventHandler SampleEvent;
可以通过Ispy查看EventHandler代码,实际上就是一个委托声明:
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e) where TEventArgs : EventArgs;
目前我在学习SharePoint 2013 和 2010 的区别,下面我们通过SharePoint 2013 升级到2010 的事件学习事件的使用:
static class Program
{
static void Main(string[] args)
{
var sharePoint2010 = new SharePoint2010();
var sharePoint2013 = new SharePoint2013();
//订阅事件
sharePoint2013.beforeUpgradeEvent += sharePoint2013_beforeUpgradeEvent;
sharePoint2013.afterUpgradeEvent += sharePoint2013_afterUpgradeEvent;
sharePoint2013.Upgrade(sharePoint2010);
}
static void sharePoint2013_afterUpgradeEvent(object sender, AfterUpgradeEventArgs e)
{
Console.WriteLine("The upgrade process is {0}", e.IsSuccessful == true ? "successful" : "failed");
}
static void sharePoint2013_beforeUpgradeEvent(object sender, BeforeUpgradeEventArgs e)
{
Console.WriteLine("Before upgrade...");
}
}
//声明委托
public delegate void BeforeUpgrade(object sender, BeforeUpgradeEventArgs e);
public delegate void AfterUpgrade(object sender, AfterUpgradeEventArgs e);
public class SharePoint2010
{
}
public class SharePoint2013
{
public void Upgrade(SharePoint2010 sharePoint2010)
{
//更新过程
var beforeUpgrade = new BeforeUpgradeEventArgs();
Upgrading(beforeUpgrade);
Console.WriteLine("During upgrade...");
var afterUpgrade = new AfterUpgradeEventArgs(true);
Upgraded(afterUpgrade);
}
//声明事件
public event BeforeUpgrade beforeUpgradeEvent;
public event AfterUpgrade afterUpgradeEvent;
//触发事件
protected virtual void Upgrading(BeforeUpgradeEventArgs e)
{
//触发事件判断是否存在
if (beforeUpgradeEvent != null)
{
beforeUpgradeEvent(this, e);
}
}
protected virtual void Upgraded(AfterUpgradeEventArgs e)
{
if (afterUpgradeEvent != null)
{
afterUpgradeEvent(this, e);
}
}
}
//升级前事件的发布
public class BeforeUpgradeEventArgs : EventArgs
{
public bool IsContinue { get; set; }
public BeforeUpgradeEventArgs()
{
IsContinue = true;
}
}
//升级后事件的发布
public class AfterUpgradeEventArgs : EventArgs
{
public bool IsSuccessful { get; private set; }
public AfterUpgradeEventArgs(bool isSuccessful)
{
IsSuccessful = isSuccessful;
}
}
//Before upgrade...
//During upgrade...
//The upgrade process is successful
通过这样一个例子,我想对于事件的了解更深刻了。另外说明下,如果是静态事件的话,触发事件的this参数还是要填上null的。
关于delegate和event的研究就这些,这里有更深入的讲解,是大牛的博客,贴一个:http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html
如果有错,欢迎纠正