Why can't I use/cast an Action for/to a ThreadStart? Why can't I use/cast an Action for/to a ThreadStart? multithreading multithreading

Why can't I use/cast an Action for/to a ThreadStart?


As others have noted, the problem is that delegate types are not "structural". That is, they do not have equivalence based on their "structure".

Now, this is arguably a good thing for some types. If you have

struct MyRectangle { int x; int y; int width; int height; ... }

and

struct YourRectangle { int x1; int y1; int x2; int y2; ... } 

obviously it would be a mistake to allow instances of MyRectangle to be assigned to variables of YourRectangle, just because they both consisted of four ints. The semantics of the ints are different and therefore the types are not equivalent.

The same is, in theory, true of delegates. You could have

delegate int Pure(string x);delegate int Func(string x);

where a "pure" function is one with no side effects and the same output given the same input. Since every Pure is logically a Func, but every Func is not necessarily a Pure, there shouldn't be structural typing between them.

In practice of course the type system does not support notions like "pure function" very well. And in practice, the vast majority of attempts to convert between delegate types are perfectly safe: converting from a Func<int, bool> to a Predicate<int> and so on.

So, two things, one looking backwards and one looking forwards. Backwards: if we had to do it all over again, I think delegates would probably be structurally typed in the CLI. You don't always know what features are going to be useful when you design a brand new framework, and non-structural delegate types have thus far turned out to be not as useful as perhaps anticipated. Forwards: I expect to see more features in future versions of the CLR that enable more structural typing. The "no pia" feature in C# 4, for example, is about making two types that are semantically and structurally the same, but defined in different assemblies, logically unify structurally.


I believe this should work?

Action doIt;doIt = () => MyMethod("test");Thread t;t = new Thread(doIt.Invoke);t.Start();


The basic form of this error is:

delegate void d1();delegate void d2();d1 a;d2 b;b = a;Error Cannot implicitly convert type 'ConsoleDemo1.d1' to 'ConsoleDemo1.d2'

So you could 'solve' your first sample by using the correct delegate type:

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