-
The new switch expression introduced in C# 8.0 doesn't support delegate types.
Using either lambda expression or method name will produce the following error:
|
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 1 reply
-
It's not a problem of switch expression. Current C# compiler are not support type guessing of delegate in many situation. I think there was a proposal to let it always fallback to Actually I think you need to made it into Action action = str switch {
"a" => () => MethodA(args),
"b" => () => MethodB(args),
"c" => () => MethodC(args),
}; |
Beta Was this translation helpful? Give feedback.
-
@Thaina |
Beta Was this translation helpful? Give feedback.
-
@HazyFish Yeah sorry, I don't have 8.0 compiler at hand so my suggestion is not really did tested This also not working However like so, this is not a problem of switch expression per se. This is the problem of C# compiler that cannot made a type out of pure lambda expression But maybe the feature related to targeted type might solve this problem #2389 #2460 #2473 Around this time you might need to explicitly put a type on all cases var action = str switch {
"a" => new Action(() => MethodA(args)),
"b" => new Action(() => MethodB(args)),
"c" => new Action(() => MethodC(args)),
}; |
Beta Was this translation helpful? Give feedback.
-
Yeah, you are right. |
Beta Was this translation helpful? Give feedback.
-
SharpLab.io is a good place to try these things out ... this works, using the current master branch of Roslyn: using System;
public class C {
public void MethodA(string[] args) { }
public void MethodB(string[] args) { }
public void MethodC(string[] args) { }
public void MethodD(string[] args) { }
public void M(string s, string[] args) {
Action action = s switch {
"a" => () => MethodA(args),
"b" => () => MethodB(args),
"c" => () => MethodC(args),
_ => () => MethodD(args)
};
}
} This is essentially what @Thaina suggested, but with a default case added at the end. |
Beta Was this translation helpful? Give feedback.
-
This has to do with target-typing. Method groups, by default, do not have a type and must be converted to a delegate type. This can be done through target-typing, but not all expressions allow target-typing through them. @HazyFish, the version of the compiler you're using does not support the changes made for #2389. Ternaries also do not currently support target-typing like this, but it has been proposed and championed here: #2460. |
Beta Was this translation helpful? Give feedback.
-
I think target-typing is only part of the story. It's possible to make the switch expression happy without target typing by explicitly casting one of the lambdas: public void M(string s, string[] args)
{
var action = s switch {
"a" => (Action)(() => MethodA(args)),
"b" => () => MethodB(args),
"c" => () => MethodC(args),
_ => () => MethodD(args)
};
} But using target typing makes for a neater solution as no cast is needed inside the switch expression. It isn't limited to explicitly typed variables either, eg it can be used with expression bodied methods: public Action M(string s, string[] args)
=> s switch {
"a" => () => MethodA(args),
"b" => () => MethodB(args),
"c" => () => MethodC(args),
_ => () => MethodD(args)
}; |
Beta Was this translation helpful? Give feedback.
-
Yes. Switch expressions attempt to find a common type between all arms. If you cast on the first branch, we get a candidate type: |
Beta Was this translation helpful? Give feedback.
-
@333fred, and an excellent job you guys have done of all that. The ease with which a switch expression can be expressed and have its type inferred from the initial release of the feature really is impressive. 👍 |
Beta Was this translation helpful? Give feedback.
-
Thank @gafter, he did all the real work :D |
Beta Was this translation helpful? Give feedback.
This has to do with target-typing. Method groups, by default, do not have a type and must be converted to a delegate type. This can be done through target-typing, but not all expressions allow target-typing through them. @HazyFish, the version of the compiler you're using does not support the changes made for #2389. Ternaries also do not currently support target-typing like this, but it has been proposed and championed here: #2460.