以接口为基类的三元表达式

Wil*_*iam 8 if-statement ternary-operator c#-4.0

我试图创建一个三元表达式,我收到以下错误

"无法确定条件表达式的类型,因为LiveSubscription和DisconnectedSubscription之间没有隐式转换"

同样的逻辑在if语句中起作用,但我想理解为什么它不能在三元表达式中起作用 -

以下是我要做的事情的要点:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我总是可以将它切换到if/else但我想先了解出了什么问题!

Dan*_*rth 10

您需要将至少一个操作数强制转换为IClientSubscription:

Subscription = (IsLive)
            ? (IClientSubscription)new LiveSubscription()
            : new DisconnectedSubscription();
Run Code Online (Sandbox Code Playgroud)

原因是三元表达式是某种类型,由操作数决定.基本上,它尝试将第二个操作数转换为第一个操作数,反之亦然.两者都失败了,因为LiveSubscription不是DisconnectedSubscription,反之亦然.
编译器不检查两者是否共享公共基类型.


试着在评论中回答你的问题:

不,三元表达式不是某种对象,但三元表达式是赋值的右手部分.赋值的每个右手部分表达式都具有某种类型,否则将该表达式赋值给左侧的变量是不可能的.
例子:

  • var x = Guid.NewGuid()

    右侧表达式(Guid.NewGuid())属于类型Guid,因为该方法NewGuid()返回一个Guid.

  • var x = y.SomeMethod()

    右侧表达式是返回类型的类型SomeMethod().

  • var x = IsLive ? "a" : 1

    这显然是无效的,不是吗?应该x是什么类型的?A string还是int
    这将导致与您的代码完全相同的错误消息.

  • 你的例子有点改变:

    var subscription = (IsLive) ? new LiveSubscription()
                                : new DisconnectedSubscription();
    
    Run Code Online (Sandbox Code Playgroud)

    注意var之前subscription,我们现在初始化一个新变量,而不是现有变量.我想即使在这里,问题显然是什么:应该subscription是什么类型?LiveSubscription还是DisconnectedSubscription?它既不是,也可能是因为IsLive它需要是一个或另一个.

关于比较if:

在您的代码中,您正在为隐式强制转换分配新LiveSubscription实例或新DisconnectedSubscription实例,因为编译器知道它是类型和两者,并且可以隐式转换为该接口. 使用三元表达式的赋值有点不同,因为编译器首先尝试计算三元表达式,然后才尝试将其赋值给它.这意味着编译器不知道三元表达式的结果必须是类型.SubscriptionIClientSubscriptionSubscriptionIClientSubscriptionLiveSubscriptionDisconnectedSubscription
SubscriptionIClientSubscription