我正在慢慢地围绕代表,因为委托的签名必须与委托方法的签名相匹配。
但是,请查看以下代码。
public static void Save()
{
ThreadStart threadStart = delegate
{
SaveToDatabase();
};
new Thread(threadStart).Start();
}
private static void SaveToDatabase() { }
我现在很难过,因为委托会返回void
(因为那是SaveToDatabase()
)但是,它显然会返回ThreadStart
......或者是它?
如果我要编写自己的委托,我将不知道如何实现这一点,因为委托必须是无效的,以匹配SaveToDatabase()
的返回类型。但它不可能;它的类型为ThreadStart
!
我的问题是,我是否完全误解了或者是否因为一些.NET技巧而成为可能?如果我想写这个方法但是创建我自己的委托,我会怎么做?
答案 0 :(得分: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
。对于该变量,我们可以指定 ANY 函数,该函数接受单个字符串参数并返回一个整数。请注意,我们分配了函数本身,而不是该函数的结果。这就像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
变量。
所以现在这就像上面的例子。只需将DelegateType
替换为ThreadStart
,将delegateInstance
替换为threadStart
,将SomeFunction
替换为__ASDASDASD6546549871
。
现在有意义吗?
答案 1 :(得分:4)
我现在感到困惑,因为委托返回void(因为这就是SaveToDatabase())但是,它显然返回了一个ThreadStart ......或者是它?
如果我要修改自己的委托,我不知道如何实现这一点,因为委托必须是无效的,以匹配SaveToDatabase()的返回类型,但不能因为它是类型的ThreadStart!
ThreadStart被定义为委托。实际上,它被定义为
public delegate void ThreadStart();
因此,您的代码未返回委托或ThreadStart
。它只是定义一个匹配ThreadStart
委托定义的函数。 Thread
构造函数需要ThreadStart
委托,您已将其定义为变量threadStart
,该变量指向SaveToDatabase
函数。
我倾向于将委托视为旧的C ++术语“函数指针”。代表允许我们指定应将哪种函数(参数和返回类型)作为参数传递给另一个函数。
我的问题是,我是否完全误解了或者是否因为一些.NET技巧而成为可能?如果我想写这个方法但是创建我自己的委托,我会怎么做?
我想你可能误会了。但要具体回答这个问题,您要编写的方法只需要匹配委托类型指定的定义,在本例中为ThreadStart。该方法定义必须返回void
并且不接受任何参数。您的SaveToDatabase
方法与此委托类型匹配,因此是要创建的正确委托方法。
答案 2 :(得分:2)
当您要运行管理的子流程时,将要执行的方法由ThreadStart
或ParameterizedThreadStart
表示,但SaveToDatabase
为void
且它将使用void
签名执行,而不是ThreadStart
类型。
来自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);
}
}
答案 3 :(得分:2)
来自MSDN
委托是引用方法的类型。为委托分配方法后,其行为与该方法完全相同。委托方法可以像任何其他方法一样使用,带有参数和返回值,如下例所示:
public delegate int PerformCalculation(int x, int y);
因此委托的返回类型将与它委派的方法的返回类型相匹配。
可以将与委托签名匹配的任何方法(包括返回类型和参数)分配给委托。这使得可以以编程方式更改方法调用,并将新代码插入现有类中。只要您知道代理人的签名,就可以指定自己的委托方法。