3

我以前没有使用过代表,我正在尝试按照我书中的教程来弄清楚它们。

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

在我正在编写的教程中,将以下代码添加到汽车类中:

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 < 6; i++)
        c1.Accelerate(20);
    Console.ReadLine();
}

public static void OnCarEngineEvent(string msg)
{
    Console.WriteLine("\n***** Message From Car Object *****");
    Console.WriteLine("=> {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让我失望...

4

4 回答 4

11

定义委托

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

delegate string MyHandler(int value1, string value2);

定义一个委托类型,该类型可以指向一个以 ( int, string) 作为参数类型的方法并返回一个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);

当然,myHandlercan be null,所以你需要先检查一下,否则你会得到一个NullReferenceException. 毕竟,你不能在null.

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

所以,他们检查:

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

或几乎等效,在 C# 6 中:(请注意,result将是nullwhen myHandleris null。)

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

为什么是代表?

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

于 2013-03-05T16:50:58.770 回答
0

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

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

于 2013-03-05T16:21:31.450 回答
0

listOfHandlers就像一个引用变量,除了方法。

现在,如果它甚至不包含方法,您不想调用listOfHandlers包含的任何方法,因此您检查以确保它不是null第一个。

null委托是尚未为其定义方法的委托。

于 2013-03-05T16:21:38.340 回答
0

Delegates 是 .Net 中的一种引用类型,并且与所有其他引用类型一样,都使用nullto start 的值进行初始化。null检查只是查看它是否已初始化为一个值。如果没有侦听器,则调用委托不会报告任何内容

于 2013-03-05T16:21:39.990 回答