【问题标题】:Ternary Expression with Interfaces as a Base Class以接口为基类的三元表达式
【发布时间】:2012-04-06 07:36:50
【问题描述】:

我正在尝试创建三元表达式,但出现以下错误

“无法确定条件表达式的类型,因为 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();
        }
    }
}

我总是可以将其切换为 if/else,但我想先了解发生了什么问题!

【问题讨论】:

    标签: c#-4.0 if-statement ternary-operator


    【解决方案1】:

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

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

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


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

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

    • var x = Guid.NewGuid()

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

    • var x = y.SomeMethod()

      右边的表达式是SomeMethod()的返回类型。

    • var x = IsLive ? "a" : 1

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

    • 你的例子有点改变:

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

      注意subscription 之前的var,我们现在初始化一个新变量,而不是现有变量。我认为即使在这里,问题出在哪里也很明显:subscription 应该是什么类型? LiveSubscription 还是 DisconnectedSubscription?两者都不是,因为取决于IsLive,它必须是两者之一。

    关于与if的比较:

    在您将新的LiveSubscription 实例或新的DisconnectedSubscription 实例分配给Subscription 的代码中,正在发生对IClientSubscription 的隐式转换,因为编译器知道Subscription 的类型为IClientSubscription LiveSubscriptionDisconnectedSubscription 都可以隐式转换为该接口。
    三元表达式的赋值有点不同,因为编译器首先尝试评估三元表达式,然后才尝试将其分配给Subscription。这意味着编译器不知道三元表达式的结果需要是IClientSubscription类型。

    【讨论】:

    • “三元表达式属于某种类型”是什么意思?这对使用三元表达式和等效的 if/else 语句有什么影响?我的印象是三元表达式是简单的句法糖——但有时会更多吗?
    • @William:请阅读完整答案,尤其是您引用的句子之后的段落。我认为这很清楚。
    • 我阅读了完整的答案,但我不确定使用三元组与 if 语句有何影响。即为什么是某种类型的三元表达式?它们是某种物体吗?
    • @William:请查看更新。我希望这使它更清楚一点。我想,Eric 或 Jon 可以用更少的词更清楚地解释它。
    猜你喜欢
    • 2015-07-13
    • 2022-01-26
    • 2011-04-06
    • 2023-03-19
    • 2017-12-24
    • 2021-07-10
    • 2017-11-16
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多