Conditional statement, general delegate, unnecessary

I am having this strange conditional expression problem when setting the value of Action<T> . It is not that I do not know how to get around this, as it is quite easy to solve using the usual if .

Here is my problem:

 public class Test { public bool Foo { get; set; } public Action<bool> Action { get; set; } public void A() { Action = Foo ? B : C;//Gives compiler error } public void B(bool value) { } public void C(bool value) { } } 

This gives me a compiler error with a message

There is no implicit conversion between a “method group” and a “method group”.

Which is strange, since I cannot understand why this would be illegal.

By the way, the syntax below will make this valid (from the point of view of compilers):

  public void A() { Action = Foo ? (Action<bool>) B : C; } 

So maybe you can read the question, how, why is casting necessary?

+8
compiler-construction generics c # delegates
source share
4 answers

You combine two similar concepts:

A) A group of methods. A method group is one or more C # methods with the same name. This is an abstraction used mainly by the compiler; you cannot go around a group of methods. All you can do with a group of methods is call it or create a delegate from it. You can implicitly create a delegate from a method group if the type labels match.

B) The delegate. You know what a delegate is; it has a special type signature and refers directly to the method. Besides calling it, you can pass it on and treat it like an object of the first class.

So, in the first example, your expression returns a group of methods B on the one hand and another group of methods C on the other. The ternary operator must return the same type on both sides, but it does not know what to do on both sides; the type of the variable to which you assigned the result ( Action<bool> ) does not determine the type of expression. So this is ambiguous.

In the second example, you legally passed method group B Action<bool> delegate on one side of the ternary operator. In the process of trying to eliminate this expression, the compiler tries to drop each side to the type of the other side. It can successfully pass the group of C methods to the Action<bool> , so it does this and the expression is legal.

+2
source share

Because B and C are not actually delegates. These are groups of methods, and they can be forcibly converted to delegates (in particular, Action<bool> ), but they are not the same thing.

The type of the conditional expression must be consistent on both branches, and since B and C are currently groups of methods (which are not typed), the compiler cannot determine what type should be. As he tells you, there is no implicit conversion between them.

In addition, he cannot (or at least not) look at the other side of the assignment operator and say "oh, this should be an Action<bool> ".

When you add a cast, the type of the expression of the left branch becomes Action<bool> , and there is an implicit conversion between the group of methods on the other side and delegation, so the compiler is happy again: the type is the whole expression Action<bool> .

+1
source share

I think Eric will tell me again that my reasoning is a little wrong , but I will give it a try anyway and hope to fix it :-)

A group of methods, for example B , has no type, it is not an object ( B.GetType() not going to compile).
It can be easily converted to type, so an implicit cast exists. Example:

 Action<bool> a = B; // implicit cast taking place. 

However, as you see in the related question, the triple expression tries to find a return type that matches both sides of the expression. He does not know that conversion to Action<bool> will happen later. Since groups of methods are not types as such, there is no conversion between them, and B cannot be converted to C , and therefore the compiler complains about it.

By discarding any part of the ternary expression on the Action<bool> , you tell the compiler that the type of the return type must be this type, and it checks to see if the other part of the ternary expression supports implicit casting to this type. Since this is so, the code will be compiled.

0
source share

An action is a specific delegate class, and there is no implicit conversion available from / to a regular delegate with a similar signature.

-one
source share

All Articles