Terminal expression with interfaces as a base class

I am trying to create a ternary expression and I get the following error

"The type of conditional expression cannot be determined because there is no implicit conversion between LiveSubscription and DisconnectedSubscription"

The same logic works in an if statement, but I would like to understand why it won't work in a triple expression -

Here is the gist of what I'm trying to do:

public interface IClientSubscription { bool TryDisconnect(); } public class LiveSubscription : IClientSubscription { public bool TryDisconnect() { return true; } } public class DisconnectedSubscription : IClientSubscription { public bool TryDisconnect() { return true; } } public class ConnectionManager { public readonly IClientSubscription Subscription; public ConnectionManager(bool IsLive) { // This throws the exception Subscription = (IsLive) ? new LiveSubscription() : new DisconnectedSubscription(); // This works if (IsLive) { Subscription = new LiveSubscription(); } else { Subscription = new DisconnectedSubscription(); } } } 

I could always switch it to if / else, but I wanted to first understand what was going wrong!

+6
source share
1 answer

You need to specify at least one of the operands on IClientSubscription :

 Subscription = (IsLive) ? (IClientSubscription)new LiveSubscription() : new DisconnectedSubscription(); 

The reason is that the triple expression has a certain type, which is determined by the operands. Basically, it tries to pass the second operand to the type of the first or vice versa. Both do not work here because LiveSubscription not DisconnectedSubscription and vice versa.
The compiler does not check if the common database type is common.


Trying to answer your question in a comment:

No, ternary expressions are not some kind of object, but the triple expression is the right part of the task. Each expression on the right side of the assignment has a specific type, otherwise it would be impossible to assign this expression to a variable on the left.
Examples:

  • var x = Guid.NewGuid()

    The correct expression ( Guid.NewGuid() ) is of type Guid because the NewGuid() method returns a Guid .

  • var x = y.SomeMethod()

    The right-hand side expression refers to the return type of SomeMethod() .

  • var x = IsLive ? "a" : 1

    This is clearly not valid, is it? What type should be x ? A string or int ?
    This will result in the same error message that you had with your code.

  • Your example has changed a bit:

     var subscription = (IsLive) ? new LiveSubscription() : new DisconnectedSubscription(); 

    Note var before subscription , we are now initializing a new variable, not an existing one. I think that here, obviously, there is the problem: what type should the subscription be? LiveSubscription or DisconnectedSubscription ? It cannot be either because depending on IsLive it should be either one or the other.

About comparison with if :

In the code where you assign a new instance of LiveSubscription or a new instance of DisconnectedSubscription to subscription , an implicit conversion to IClientSubscription because the compiler knows that the subscription is of type IClientSubscription and both LiveSubscription and DisconnectedSubscription can be implicitly converted to this interface.
Assignment with a ternary expression is slightly different, because the compiler first tries to evaluate the ternary expression, and only then does it try to assign its subscription . This means that the compiler does not know that the result of the triple expression must be of type IClientSubscription .

+8
source

Source: https://habr.com/ru/post/911342/


All Articles