与创建委托相比,关键字委托如何工作

Dav*_*ave 7 c# delegates

我正慢慢地围绕代表,因为委托的签名必须与它委派的方法相匹配.

但是,请查看以下代码.

public static void Save()
{
    ThreadStart threadStart = delegate
    {
        SaveToDatabase();
    };
    new Thread(threadStart).Start();
}

private static void SaveToDatabase() { }
Run Code Online (Sandbox Code Playgroud)

我现在感到难过,因为代表返回void(因为那是什么SaveToDatabase())但是,它显然正在返回ThreadStart......或者是它?

如果我要编写自己的委托,我不知道如何实现这一点,因为委托必须是无效的,以匹配返回类型SaveToDatabase().但它不可能; 它会是类型ThreadStart!

我的问题是,我是完全误解了还是通过一些.NET技巧使这成为可能?如果我想写这个方法但是创建我自己的委托,我该怎么办?

Vil*_*lx- 5

"委托"这个词有点滥用.使用类和对象更容易."类"就像是对象的蓝图."对象"是内存中的实际实例,它遵循类的蓝图.

对于代表们,我们使用相同的词,因此我怀疑你的困惑.请考虑以下代码:

class Main
{
    public delegate int DelegateType(string x);
    public int SomeFunction(string y) { return int.Parse(y)*2; }
    public void Main()
    {
        DelegateType delegateInstance = null;
        delegateInstance = SomeFunction;
        int z = delegateInstance("21");
        Console.WriteLine(z);
    }
}
Run Code Online (Sandbox Code Playgroud)

该代码输出"42".

DelegateType是委托的类型.就像一个类是对象的蓝图一样,委托是一个函数的蓝图.

所以稍后我们创建一个名为delegateInstancetype 的变量DelegateType.对于该变量,我们可以分配ANY函数,该函数接受单个字符串参数并返回一个整数.注意,我们分配了函数本身,而不是该函数的结果.这就像delegateInstance变量现在是该函数的同义词.事实上,正如后面所展示的那样,我们现在可以delegateInstance用来称呼那个功能!好像delegateInstance是一个功能本身.但是,由于它是可变的,我们也可以做我们通常对变量做的所有事情 - 比如将它们作为参数传递给其他函数,或者甚至从其他函数返回(一个返回函数的函数!)绕过那个!)

好的,让我们看看困扰你的代码.

public static void Save()
{
    ThreadStart threadStart = delegate
    {
        SaveToDatabase();
    };
    new Thread(threadStart).Start();
}

private static void SaveToDatabase() { }
Run Code Online (Sandbox Code Playgroud)

首先要注意的是你使用了一个anonymous delegate.另一个误用的术语.编译时,会产生如下结果:

public static void Save()
{
    ThreadStart threadStart;
    threadStart = __ASDASDASD6546549871;
    var tmp = new Thread(threadStart);
    tmp.Start();
}

private static void SaveToDatabase() { }

private void __ASDASDASD6546549871()
{
    SaveToDatabase();
}
Run Code Online (Sandbox Code Playgroud)

请注意,您的匿名函数实际上已转换为具有随机名称的完全常规函数,然后将该函数分配给该threadStart变量.

所以现在这就像上面的例子.只需更换DelegateTypeThreadStart,delegateInstancethreadStartSomeFunction__ASDASDASD6546549871.

现在有意义吗?


vil*_*der 4

我现在被难住了,因为委托返回 void (这就是 SaveToDatabase() 的意思),但是,它显然返回 ThreadStart...或者是吗?

如果我要纠正我自己的委托,我将不知道如何实现这一点,因为委托必须为 void 才能匹配 SaveToDatabase() 的返回类型,但不能,因为它的类型为 ThreadStart!

ThreadStart被定义为委托。事实上,它被定义为

public delegate void ThreadStart();
Run Code Online (Sandbox Code Playgroud)

所以你的代码没有返回委托或ThreadStart. 它只是定义一个ThreadStart与委托定义匹配的函数。构造函数Thread需要一个ThreadStart委托,您已将其定义为threadStart指向该SaveToDatabase函数的变量。

我倾向于将委托视为旧的 C++ 术语“函数指针”。委托允许我们指定哪种函数(参数和返回类型)应作为参数传递给另一个函数。

我的问题是,我是否完全误解了,或者这是由某些 .NET 欺骗造成的?如果我想编写这个方法但创建自己的委托,我该怎么做?

我想你可能误会了。但为了具体回答这个问题,您编写的方法只需要与委托类型指定的定义相匹配,在本例中为 ThreadStart。该方法定义必须返回void并且不接受任何参数。您的SaveToDatabase方法与此委托类型匹配,因此是要创建的正确委托方法。