为什么我不能使用/强制转换/用于ThreadStart?

Roo*_*ian 9 c# multithreading delegates action

两者都是委托并具有相同的签名,但我不能将Action用作ThreadStart.

为什么?

Action doIt;
doIt = () => MyMethod("test");
Thread t;

t = new Thread(doIt);
t.Start();
Run Code Online (Sandbox Code Playgroud)

但这似乎有效:

Thread t;

t = new Thread(() => MyMethod("test"));
t.Start();
Run Code Online (Sandbox Code Playgroud)

Eri*_*ert 21

正如其他人所指出的那样,问题在于委托类型不是"结构性的".也就是说,它们没有基于其"结构"的等价.

现在,对于某些类型来说,这可能是件好事.如果你有

struct MyRectangle { int x; int y; int width; int height; ... }
Run Code Online (Sandbox Code Playgroud)

struct YourRectangle { int x1; int y1; int x2; int y2; ... } 
Run Code Online (Sandbox Code Playgroud)

很明显,允许将MyRectangle的实例分配给YourRectangle的变量是错误的,因为它们都包含四个整数.整数的语义不同,因此类型不等同.

从理论上讲,对代表来说也是如此.你可以有

delegate int Pure(string x);
delegate int Func(string x);
Run Code Online (Sandbox Code Playgroud)

其中"纯"函数是没有副作用的函数,并且在给定相同输入的情况下输出相同.由于每个Pure在逻辑上都是Func,但每个Func不一定是Pure,因此它们之间不应该有结构类型.

在实践中,类型系统当然不能很好地支持像"纯函数"这样的概念.在实践中,绝大多数在委托类型之间进行转换的尝试都非常安全:从a转换Func<int, bool>为a Predicate<int>等等.

所以,有两件事,一件是向后看,另一件是向前看.倒退:如果我们不得不重新做一遍,我认为代表可能会在CLI中进行结构化输入.在设计一个全新的框架时,你并不总是知道哪些特性会有用,而迄今为止,非结构化的委托类型并不像预期的那样有用.前瞻:我希望在未来版本的CLR中看到更多功能,以实现更多的结构类型.例如,C#4中的"无pia"特征是关于使两种类型在语义上和结构上相同,但在不同的集合中定义,在逻辑上在结构上统一.


Hen*_*man 5

该错误的基本形式是:

delegate void d1();
delegate void d2();
d1 a;
d2 b;
b = a;

Error Cannot implicitly convert type 'ConsoleDemo1.d1' to 'ConsoleDemo1.d2'
Run Code Online (Sandbox Code Playgroud)

因此,您可以使用正确的委托类型来“解决”您的第一个示例:

//Action doIt;
ThreadStart doIt;
doIt = () => MyMethod("test");
Thread t = new Thread(doIt);
Run Code Online (Sandbox Code Playgroud)


Spe*_*ort 5

我相信这应该有效?

Action doIt;
doIt = () => MyMethod("test");
Thread t;

t = new Thread(doIt.Invoke);
t.Start();
Run Code Online (Sandbox Code Playgroud)