人问好,它内部调用了EnglishGreeting方法来完成具体的问候。现在假设我们需要提供不同的问候方式,例如中文或法语,这时,如果直接修改GreetPeople以决定使用哪种语言的问候,代码会变得耦合度很高。为了解决这个问题,我们可以引入C#中的委托。
委托在C#中是一种类型,它代表了一个方法的引用,允许我们将方法作为参数传递给其他方法,或者将其存储在变量中。这种特性使得我们可以在运行时动态地决定调用哪个方法,实现了代码的灵活性和解耦。
1.1.2将方法绑定到委托
在C#中,我们可以创建一个委托类型,然后实例化这个委托,将其绑定到特定的方法。例如,我们可以定义一个代表问候方法的委托:
```csharp
public delegate void GreetingDelegate(string name);
```
接着,我们可以在GreetPeople方法中创建一个GreetingDelegate实例,并将其绑定到EnglishGreeting或FrenchGreeting等方法:
```csharp
public void GreetPeople(string name, GreetingDelegate greetMethod)
{
// 做一些初始化操作
greetMethod(name);
}
public void EnglishGreeting(string name)
{
Console.WriteLine("Good Morning, " + name);
}
public void FrenchGreeting(string name)
{
Console.WriteLine("Bonjour, " + name);
}
```
这样,GreetPeople就可以接受任何符合GreetingDelegate签名的方法,从而实现灵活的问候逻辑。
1.2事件的由来
事件是基于委托的,它提供了一种安全的方式来发布通知,当某个特定情况发生时,订阅该事件的客户端可以执行相应的操作。事件的主要目的是为了更好地封装,避免直接访问对象的内部状态,同时也限制了非所有者对事件的滥用。
1.2.1更好的封装性
通过事件,我们可以隐藏内部状态的变化,只允许特定的外部代码(即事件订阅者)响应这些变化。这样,即便对象的实现细节发生了改变,只要保持事件接口不变,就不会影响到订阅者。
1.2.2限制类型能力
事件还提供了类型安全,确保只有正确签名的方法能够订阅事件,避免了不兼容方法的错误调用。
1.3委托的编译代码
C#编译器会将委托实例化和方法调用转化为IL代码,涉及到对委托实例的创建、方法的查找和调用。理解这部分内容有助于我们更好地优化代码性能。
1.4.NET框架中的委托和事件
.NET Framework广泛使用委托和事件,如UI控件的事件处理、线程间的通信等。Observer设计模式是事件处理的一个典型应用场景,它定义了对象间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
1.4.1范例说明
例如,一个数据提供者类(Subject)可以通过事件通知订阅者(Observer)数据已更新:
```csharp
public class Subject
{
public event DataUpdatedHandler DataUpdated;
public delegate void DataUpdatedHandler(object sender, EventArgs e);
public void NotifyDataUpdated()
{
if (DataUpdated != null)
DataUpdated(this, EventArgs.Empty);
}
}
public class Observer
{
public void Subscribe(Subject subject)
{
subject.DataUpdated += OnDataUpdated;
}
private void OnDataUpdated(object sender, EventArgs e)
{
// 处理数据更新
}
}
```
1.4.2Observer设计模式简介
Observer模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。
1.4.3实现范例的Observer设计模式
上面的代码就是一个简单的Observer模式实现,Subject通过事件来通知Observer数据变化。
1.4.4.NET框架中的委托与事件
.NET Framework中的许多类,如Control类,都使用了事件来处理用户交互,例如Click事件。这使得我们可以轻松地编写事件驱动的程序。
1.5委托进阶
1.5.1为什么委托定义的返回值通常都为void?
通常,事件处理方法不需要返回值,因为它们主要负责响应事件,而不是返回结果。但不是绝对的,根据实际需求,也可以定义有返回值的委托。
1.5.2如何让事件只允许一个客户订阅?
可以自定义事件访问器,仅允许单个订阅者。在.NET中,这通常通过private set访问修饰符来实现。
1.5.3获得多个返回值与异常处理
可以通过多播委托(如EventHandler<TEventArgs>)传递自定义的EventArgs类来携带多个返回值,同时,异常处理通常在事件处理方法内进行。
1.6订阅者方法超时的处理
当事件处理方法执行时间过长导致阻塞,可以考虑使用异步委托或Task来处理超时问题。
1.7委托和方法的异步调用
C#支持异步调用委托,如BeginInvoke/EndInvoke方法,或使用async/await关键字配合Task来实现异步事件处理。
1.8总结
委托和事件是C#中强大的特性,它们在实现事件驱动编程、回调机制以及观察者模式等方面发挥着重要作用。理解并熟练掌握委托和事件的使用,能显著提高C#编程的效率和灵活性。