C#代表教程工作

我之前没有使用过代理人,我正试图按照我的书中的教程来解决这些问题。

到目前为止,我已经发现委托可以与类的方法一起使用,该类返回相同类型的对象,并且与调用委托的代理重载(如果我错了,请纠正我)。

在我正在研究的教程中,以下代码被添加到Car Class:

public delegate void CarEngineHandler(string msgForCaller); private CarEngineHandler listOfHandlers; public void RegisterWithCarEngine(CarEngineHandler methodToCall) { listOfHandlers = methodToCall; } 

Main控制台应用程序中,调用以下代码:

 static void Main(string[] args) { Car c1 = new Car("Slugbug", 100, 10); c1.RegisterWithCarEngine(new Car.CarEngineHandler(OnCarEngineEvent)); Console.WriteLine("**** Speeding Up ******"); for (int i = 0; i  {0}", msg); Console.WriteLine("*************************************\n"); } 

这是Accelerate方法:

 public void Accelerate(int delta) { if (carIsDead) { if (listOfHandlers != null) listOfHandlers("Sorry, this car is dead..."); } else { CurrentSpeed += delta; if (10 == (MaxSpeed - CurrentSpeed) && listOfHandlers != null) { listOfHandlers("Careful buddy! Gunna Blow!"); } } if (CurrentSpeed >= MaxSpeed) carIsDead = true; else Console.WriteLine("CurrentSpeed = {0}", CurrentSpeed); } 

我很疑惑listofHandlers究竟是如何在这里工作的? 我知道这不是任何代码的错,但我想更多地了解代理如何实际工作? 检查listofHandlersnull listofHandlers我失望……

定义代表

在C#中,您可以创建指向方法的指针。 这样的指针称为Delegate 。 委托只是方法的普通对象 。 它只能指向具有匹配参数类型和匹配返回类型的方法。

 delegate string MyHandler(int value1, string value2); 

定义一个委托类型,该类型可以指向具有( intstring )作为参数类型的方法并返回一个string

您可以在字段中存储此类委托(指向方法的指针)。

 MyHandler myhandler; 

这个委托只是一个对象,所以像任何对象一样,它可以为null

创建一个新的委托

给定一种方法:

 string X(int v1, string v2) { /* ... */ } 

您可以创建指向该方法的新委托:

 myHandler = new MyHandler(X); 

或者,由于语法糖,您可以使用这种更短的语法:

 myHandler = X; 

调用委托

在以后的任何时候,您都可以调用委托指向的方法。

 int i = 10; string s = String.Empty; string result = myHandler.Invoke(i, s); 

或者,再次感谢句法糖:

 int i = 10; string s = String.Empty; string result = myHandler(i, s); 

当然, myHandler可以为null ,因此您需要首先检查它,否则您将获得NullReferenceException 。 毕竟,您无法在null上调用实例方法。

 myHandler = null; myHandler.Invoke(10, ""); 

所以,他们检查:

 string result; if (myHandler != null) result = myHandler(i, s); 

或者几乎相同,在C#6中:(注意,当myHandlernull时, result将为null 。)

 string result = myHandler?.Invoke(i, s); 

为什么代表?

如果要使用相同的代码调用不同的方法,则可以传递一个委托,该委托指向要在对象中作为参数或字段调用的方法。 这是事件在.NET中实现的方式,以及LINQ的工作原理。

空检查是因为您可能没有listofHandlers ,否则它将为null 。 就像调用值为null的类的方法是非法的一样,也不允许调用null的委托。

委托提供了一种抽象方法调用的方法。 在Java中,您使用定义单个方法的接口,C#只允许您直接使用委托。

listOfHandlers类似于引用变量,方法除外。

现在你不想调用listOfHandlers包含的任何方法,如果它甚至不包含方法,那么你要检查以确保它首先不是null

null委托是一个委托,它没有为它定义的方法。

委托是.Net中的引用类型,并且像所有其他引用类型一样,初始化值为null以启动。 null检查只是看它是否已经初始化为一个值。 如果没有监听器,则无需通过调用委托来报告