7

我正在慢慢了解委托,因为委托的签名也必须与它委托的方法的签名相匹配。

但是,请查看以下代码。

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

private static void SaveToDatabase() { }

我现在被难住了,因为代表返回void(就是这样SaveToDatabase())但是,它显然返回了一个ThreadStart......或者是吗?

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

我的问题是,我是否完全误解了,或者这是否通过一些 .NET 诡计而成为可能?如果我想编写此方法但要创建自己的委托,我会怎么做?

4

4 回答 4

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);
    }
}

此代码输出“42”。

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

所以稍后我们创建一个名为的变量delegateInstance,它的类型为DelegateType。对于该变量,我们可以分配任何接受单个字符串参数并返回整数的函数。请注意,我们分配了函数本身,而不是该函数的结果。就像delegateInstance变量现在是该函数的同义词。确实,正如后面一行演示的那样,我们现在可以使用delegateInstance来调用该函数!就好像delegateInstance一个函数本身一样。但是,由于它是可变的,我们也可以做我们通常对变量做的所有相同的事情——比如将它们作为参数传递给其他函数,甚至从其他函数返回(一个返回函数的函数!绕着你的脑袋!)

好的,让我们看看让你感到困惑的代码。

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

private static void SaveToDatabase() { }

首先要注意的是您使用了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();
}

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

所以现在这就像上面的例子一样。只需替换DelegateTypeThreadStartdelegateInstance和。threadStart_SomeFunction__ASDASDASD6546549871

现在有意义吗?

于 2012-12-10T14:40:38.770 回答
4

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

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

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

public delegate void ThreadStart();

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

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

我的问题是,我是否完全误解了,或者这是否通过一些 .NET 诡计而成为可能?如果我想编写此方法但要创建自己的委托,我会怎么做?

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

于 2012-12-10T14:30:54.580 回答
2

当您要运行受管理的子流程时,将要执行的方法由 or 表示,ThreadStart但是ParameterizedThreadStart它将使用签名而不是类型来执行。SaveToDatabasevoidvoidThreadStart

来自 MSDN 的示例:

class Test
{
    static void Main() 
    {
        // To start a thread using a static thread procedure, use the
        // class name and method name when you create the ThreadStart
        // delegate. Beginning in version 2.0 of the .NET Framework,
        // it is not necessary to create a delegate explicityly. 
        // Specify the name of the method in the Thread constructor, 
        // and the compiler selects the correct delegate. For example:
        //
        // Thread newThread = new Thread(Work.DoWork);
        //
        ThreadStart threadDelegate = new ThreadStart(Work.DoWork);
        Thread newThread = new Thread(threadDelegate);
        newThread.Start();

        // To start a thread using an instance method for the thread 
        // procedure, use the instance variable and method name when 
        // you create the ThreadStart delegate. Beginning in version
        // 2.0 of the .NET Framework, the explicit delegate is not
        // required.
        //
        Work w = new Work();
        w.Data = 42;
        threadDelegate = new ThreadStart(w.DoMoreWork);
        newThread = new Thread(threadDelegate);
        newThread.Start();
    }
}

class Work 
{
    public static void DoWork() 
    {
        Console.WriteLine("Static thread procedure."); 
    }
    public int Data;
    public void DoMoreWork() 
    {
        Console.WriteLine("Instance thread procedure. Data={0}", Data); 
    }
}
于 2012-12-10T14:25:39.017 回答
2

来自 MSDN

委托是一种引用方法的类型。一旦为委托分配了一个方法,它的行为就与该方法完全相同。委托方法可以像任何其他方法一样使用,带有参数和返回值,如下例所示:

public delegate int PerformCalculation(int x, int y);

所以委托的返回类型将匹配它所委托的方法的返回类型。

任何与委托签名匹配的方法(包括返回类型和参数)都可以分配给委托。这使得以编程方式更改方法调用以及将新代码插入现有类成为可能。只要知道委托的签名,就可以分配自己的委托方法。

于 2012-12-10T14:31:08.480 回答