3

This code:

var userType = viewModel.UserType == UserType.Sales 
                    ? new Sales() 
                    : new Manager();

Gives me this compiler error message:

Type of conditional expression cannot be determined because there is no implicit conversion between 'Models.Sales' and 'Models.Manager'.

Why can I not initialize a var depending on the outcome of a condition? Or am I doing something wrong here?

EDIT: @Tim Schmelter, I didn't saw that post, all I could find were int and null, bool and null:

Type of conditional expression cannot be determined because there is no implicit conversion between 'string' and 'System.DBNull'

Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and <null>

Type of conditional expression cannot be determined because there is no implicit conversion between 'int' and '<null>'

But no custom types.

Community
  • 1
  • 1
Quoter
  • 4,236
  • 13
  • 47
  • 69
  • The compiler complains because, even if you use type inference, the two expressions that can be returned from the conditional operator have to be convertible to a common type. – Frédéric Hamidi Oct 20 '14 at 09:19
  • Both side of a conditional operator must return compatible type. Also variables can only be initialised to compatible types. The var keyword allows variables to be implicitly typed, the type must still be determined at compile time, it cannot be determined at runtime. You need to use `dynamic` for that. – Ben Robinson Oct 20 '14 at 09:20
  • 1
    In layman's terms - you can't answer the question "what type is `userType`", so neither can the compiler. If you were to replace `var` with the type, what would it be? –  Oct 20 '14 at 09:21
  • `var` is not `object`, but even if it was it would not compile since the conditional operator doesn't let you assign incompatible types to a variable. If you want to go that way you have to use an `if`. – Tim Schmelter Oct 20 '14 at 09:27

3 Answers3

3

You need to cast the first possibility to a common base type or interface, e.g.:

var userType = viewModel.UserType == UserType.Sales 
                    ? (IUser)new Sales() 
                    : new Manager();

Otherwise the compiler does not know what type it should create and will use Sales and so it would fail when trying to assign the Manager instance.

Christoph Fink
  • 22,727
  • 9
  • 68
  • 113
  • At the moment there is no base class those objects derive from. Thanks for the explanation. – Quoter Oct 20 '14 at 09:29
2

Because:

Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.

In your code it is impossible to convert from Sales to Manager, or visa versa.So they are incompatible types and in that case compiler fails to determine the type. C# is statically typed language (mostly) and the type of a variable can't be dynamic unless it's defined as dynamic.

Selman Genç
  • 100,147
  • 13
  • 119
  • 184
2

You need to explicitly declare userType to be the common type of Sales and Manager. For example, if they both derive from User then do this:

User userType = viewModel.UserType == UserType.Sales 
                    ? new Sales() 
                    : new Manager();
Sean
  • 60,939
  • 11
  • 97
  • 136
  • 4
    +1 People seem to have forgotten that you can actually specify a type rather than using `var` all the time. – Rhumborl Oct 20 '14 at 09:23
  • You got me on the wrong trak here too, but this does NOT work: https://dotnetfiddle.net/QdkQ3A (but this does: https://dotnetfiddle.net/aSCcfG) – Christoph Fink Oct 20 '14 at 09:36
  • @Rhumborl No, this is not related to the variable declaration or assignment, so the `var` thing is completely irrelevant. Your change will not help. In the sub-expression of form `b ? x : y` the compile-time types of `x` and `y` must be implicitly convertible to each other (in one direction). – Jeppe Stig Nielsen Nov 24 '14 at 18:41