6

In my program, we split up a large amount of data that needs to be looked over across four threads.

Thread one = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });
Thread two = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[1], param2, param3, param4, param5); });
Thread three = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[2], param2, param3, param4, param5); });
Thread four= new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[3], param2, param3, param4, param5); });

Our coding standards require that we are StyleCop compliant, as it were, and StyleCop demands the following:

SA1410: Remove the parenthesis from the anonymous method, since the delegate's parameter list is empty.

Doing that gives me this compiler error:

The call is ambiguous between the following methods or properties: 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)' and 'System.Threading.Thread.Thread(System.Threading.ThreadStart)'

I've looked into the ThreadStart and ParameterizedThreadStart objects and I just can't figure out how to get what I need done with either of those objects.

My question: how do the anonymous delegates work? What do they compile down to? In the end, I will have to get this working without the anonymous delegates, but I don't know where to begin.

Thanks for the help,

Seeker

3 Answers3

7

You have two options:

  • Ignore the StyleCop warning (recommended)
  • Change it to new ThreadStart(delegate { ... })

Explanation:

An anonymous method without parentheses (delegate { ... }) has an implicit parameter list. The compiler will give it whatever parameters are needed to match the delegate it's being used as. (Your code cannot see the parameters)
This is very useful when writing anonymous event handlers that don't use their parameters; it saves you from typing delegate(object sender, EventArgs e) { ... }.

However, when calling the Thread constructor, there are two different overloads that take two kinds of delegates.
The compiler has no way of knowing which delegate type you're trying to create, since you didn't specify a parameter list.

Community
  • 1
  • 1
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • From your description that style-cop rules sounds like a stupid idea in general. And it's description of "When an anonymous method does not contain any method parameters, the parenthesis around the parameters are optional." would be misleading too. – CodesInChaos Nov 30 '10 at 20:57
5

StyleCop is dumb.

StyleCop is implying that the two syntaxes have the same meaning. This is completely wrong. Omitting the parentheses from a delegate does not mean "this takes no arguments." It means "fill in any arguments for me, because I won't be using them anyway."

Since two different signatures of Thread:.ctor are available, each taking a different delegate type, the compiler cannot know which one to pick, since it would be just fine with either one. Adding the parentheses forces the compiler to pick the ThreadStart variant, since it is the only signature with a delegate type compatible with your anonymous method.

If you want to make StyleCop happy and have your code compile, this is one option:

Thread one = new Thread(new ThreadStart(delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); }));

This is another:

Thread one = new Thread((ThreadStart) delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });

But my suggestion would be to LART the StyleCop authors for introducing this ridiculous rule.

cdhowie
  • 158,093
  • 24
  • 286
  • 300
  • Note that both options will (AFAIK) compile identically. – SLaks Nov 30 '10 at 20:53
  • Yes, they will. The latter syntax effectively uses the syntactic sugar introduced in C# 2 that allows the omission of the `new DelegateType(...)` construct when the delegate type can be inferred from the context. The cast supplies the necessary context. – cdhowie Nov 30 '10 at 20:54
  • Can somebody with a codeplex account post this in their forum? – CodesInChaos Nov 30 '10 at 21:05
3

You could use a lambda expression instead of the delegate keyword:

Thread one = new Thread(() => NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5));
Joe White
  • 94,807
  • 60
  • 220
  • 330