Why is C#8's switch expression invalid in expression tree?
Asked Answered
I

0

6

Consider the following code in AutoMapper

CreateMap<ViewModel, ServiceModel>()
    .ForMember(
        x => x.Type,
        opt => opt.MapFrom(y =>
            y.TypeName switch
            {
                "FirstName" => typeof(FirstModel),
                "SecondName" => typeof(SecondModel),
                _ => null
            }));

I have few different cases and I want to return a specific type for each string.

The compiler disagrees:

An expression tree may not contain a switch expression.

Why is that? I would expect that this feature, neatly called expression internally performs Expression.Switch, thus should be usable in expression trees.

I know that I can substitute with ternary operator syntax. I'd like to understand why it does not work.

Edit

Thanks Sweeper for pointing that that's not actually a switch expression. Guess I got carried on the convention train and got fooled by the naming.

Ivan Stoev I'm aware it's not supported but I am curious as to why. I understand why block scope is not supported, but switch case is very simple and declarative in nature, which would fit well in an expression tree.

Edit 2 Thanks to Jeroen Mostert comment bellow, I now understand that a switch case is far from simple internally and thus it has no place in expression trees.

Infest answered 5/12, 2019 at 10:30 Comment(11)
Expression.Switch represents a switch statement, not a switch expression.Marcusmarcy
Because it's not implemented (similar to ?. operator: "An expression tree lambda may not contain a null propagating operator.", value tuples: "An expression tree may not contain a tuple literal." etc.)Obligation
AutoMapper? As Jimmy Bogard, AutoMapper's creator explains, that's not what it's for. If you end up writing so much code that a simple method would be smaller, write the simpler methodAxle
I suspect you could solve the real problem by redesigning the "model". Views expect specific view models, not abstract models with some kind of type name. So do service or data models. If you want those models to have common functionality you can use base classes, interfaces and generics. If you want to create a partial view or component that works with multiple types make it generic, or make it work with an interface implemented by all other "models".Axle
Even with switch expressions, switching works on the types themselves, not the type names. You can write x switch { FirstModel m=>..., SecondModel m=>.....}.Axle
I've solved the problem by moving the switch in a service, that's not the point. Thanks Sweeper. @IvanStoev I'll rephrase the question a bit, since I'm mostly interested in the reason behind the decision not to implement it.Infest
A switch expression is anything but simple from the compiler's point of view. It may be compiled down to a sequence of if/thens, or a full-blown switch statement, it may involve tuple deconstruction, temporaries, constructor calls... It is not, in any case, considered a primitive expression of the expression tree API, which has traditionally allowed no newcomers in any case so as not to break providers (hence also no null propagation, no tuples, etc., even though those are conceptually much simpler than switch).Awaken
"Why not?" questions are vague and hard to answer satisfactorily. The unsatisfactory answer is: did you personally do the work to add this feature to the language? The language is open-source, you want the feature, so why have you not done it yet? Seriously, why not? You've asked a why not question, and you should be able to answer it yourself. Now ask every other person in the world why they did not add the feature either, and then you will know why the feature was not added. Features do not appear magically and then need a reason to remove them!Matronymic
Moreover, you say that the feature is simple and fits well, so it should be straightforward and simple for you do to the work, right? Send the team a PR!Matronymic
@EricLippert, you seem to have made a assumption about the nature of this question. No one was asking "why haven't the C# folks done this work." I think most here assumed there was a technical or philosophical reason for the exclusion of switch expressions. So why not inform us that this is up for grabs and provide a link to the repo and contribution guide? Personally, we make extensive use of Expression Tree. And I'm considering working on this. But I really hope this isn't representative of the attitudes I will encounter.Unfamiliar
Moreover, the System.Linq.Expressions repo says it's not accepting contributions.Unfamiliar

© 2022 - 2024 — McMap. All rights reserved.