Eri*_*ert 50
到目前为止,其他答案都非常好.这是考虑它的另一种方式.
属性和字段之间的语义差异是什么?我不是说什么是技术差异,就像一个属性实际上是一对方法,等等等等等等.我的意思是,就理解程序的含义而言,有什么区别?
属性通常是类的公共成员,它表示正在建模的事物的属性.也就是说,你想制作一份报纸模型,这样你就可以制作一份报纸,然后给它一个属性发布者.出版商是报纸的财产,因此出版商是报纸类的财产.
字段通常是类的实现细节.也许Publisher属性实际上是作为字段实现的.但报纸上没有"字段",因此您不要将发布商字段作为报纸类的公共成员公开; 您将它用作Publisher属性的私有实现细节.
事件和代表有点类似.事件是模型中的事物.按钮是一个可以在单击时通知您的按钮,因此Button类具有"Click"事件.实际执行通知的委托是事件的实现细节.
Kon*_*lph 18
基本上,委托只是C(或函数指针列表)中的函数指针的包装器.
一个事件是一个更高级别的抽象,它包装一个委托的概念与方法订阅和取消订阅的方法,以这样的代表在一起.
事件是一个"属性",它公开一个add
和remove
方法(通过代码调用+=
和-=
在代码中调用)以向代理列表添加/删除订阅者.
甲代表类似于在C/C的函数指针++.它包含对方法和对象实例的引用(如果该方法是非静态的).代表通常是多播的,即它们包含对几个对象/方法对的引用.
一个事件是一个通知机制的基础上,与会代表.它公开披露的唯一内容是一对方法(添加/删除)来订阅或取消订阅通知.委托类型用于定义处理程序方法的签名,订阅者列表(通常)在内部存储为委托.
我很乐意承认这个答复没有比较代表和事件之间的区别.但是,我认为其他人为活动提供的回复以及对代表的更详细解释,您会看到两者之间的差异.更具体地说,一旦你对代表有了更清楚的了解,我认为你将在代表和事件之间获得概念上的区别.
什么帮助我理解代表是什么,将它们视为仅仅是单个方法的容器.
为了概念化委托如何是方法的"容器",请查看此示例,该示例使用委托来调用三种不同的方法 - 请注意,尽管使用相同的委托实例来调用三种不同的方法,但委托实例仅包含(或目标)在任何给定时间的一种方法.
class Program
{
delegate void MyDelegate();
static void Main()
{
//Notice how we use the same delegate instance
//to target different methods of the same signature
MyDelegate myDelegate = new MyDelegate(MethodA);
myDelegate(); //Invoke the method
myDelegate = MethodB;
myDelegate();
myDelegate = MyClass.MethodZ;
myDelegate();
Console.ReadLine();
}
static void MethodA()
{
Console.WriteLine("Method 'A' is doing work.");
}
static void MethodB()
{
Console.WriteLine("Method 'B' is doing work.");
}
class MyClass
{
public static void MethodZ()
{
Console.WriteLine("Method 'Z' of MyClass is doing work");
}
}
}
Run Code Online (Sandbox Code Playgroud)
您会注意到示例中的委托可以包含/ target任何与委托具有相同签名的方法(在我们的示例中返回void并接受零参数).如果你在这里暂停并消化这个原则,你就可以开始理解代表了.
有了这样说,让我对代表感到困惑的是,当我在代码中明确地实现委托时.上面的示例程序明确地使用了委托,但没有实际的理由这样做,因为Main()方法也可以直接调用目标方法 - 即我们刚刚完成...
static void Main()
{
MethodA();
MethodB();
MyClass.MethodZ();
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
那么什么时候我们明确地实现委托呢?他说,Jon Skeet帮我回答了这个问题
...您可以将委托类型视为有点像单个方法的接口.
知道委托是方法的容器,现在,考虑到委托就像具有单个方法的接口,请考虑以下事项:
假设我们有一个程序可以启动不同类型车辆的引擎 - 汽车,摩托车和飞机.
我们的计划将包括车辆类 - 每种车型一类.每个车辆类别负责启动自己的发动机.此外,类似于实现接口,每个类将确保其启动其自己的引擎的方法将具有所有其他类(和Main)同意的指定签名.
所以我们有这样的事情:
class VehicleProgram
{
//All vehicle classes implement their own engine starter method that has this signature
delegate void StartEngine();
static void Main()
{
//The Main doesn't know the details of starting an engine.
//It delegates the responsibility to the concrete vehicle class
foreach (StartEngine starter in GetVehicleStarters())
{
starter(); //Invoke the method
}
Console.ReadLine();
}
static List<StartEngine> GetVehicleStarters()
{
//Create a list of delegates that target the engine starter methods
List<StartEngine> starters = new List<StartEngine>();
starters.Add(Car.StartCar);
starters.Add(Motorcycle.StartMotorcycle);
starters.Add(Airplane.StartAirplane);
return (starters);
}
class Car
{
public static void StartCar()
{
Console.WriteLine("The car is starting.");
}
}
class Motorcycle
{
public static void StartMotorcycle()
{
Console.WriteLine("The motorcycle is starting.");
}
}
class Airplane
{
public static void StartAirplane()
{
Console.WriteLine("The airplane is starting.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
由于委托持有方法,我们能够实现一个设计,其中Main()只获取委托列表然后调用该方法.这种设计与我们实现接口的方式非常相似.
阅读更多关于何时使用代理而不是接口的信息
归档时间: |
|
查看次数: |
69049 次 |
最近记录: |