代码之家  ›  专栏  ›  技术社区  ›  Langdon

C#中的ternaries是有限的,有什么好的理由吗?

  •  9
  • Langdon  · 技术社区  · 16 年前

    失败:

    object o = ((1==2) ? 1 : "test");
    

    成功:

    object o;
    if (1 == 2)
    {
        o = 1;
    }
    else
    {
        o = "test";
    }
    

    无法确定条件表达式的类型,因为“int”和“string”之间没有隐式转换。

    为什么需要这样,我将这些值赋给object类型的变量。

    上面的例子是微不足道的,是的,但也有一些例子是非常有用的:

    int? subscriptionID; // comes in as a parameter
    
    EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
    {
        Value = ((subscriptionID == null) ? DBNull.Value : subscriptionID),
    }
    
    4 回复  |  直到 16 年前
        1
  •  17
  •   John Gietzen    16 年前

    使用:

    object o = ((1==2) ? (object)1 : "test");
    

    问题是,条件运算符的返回类型不能不含糊地确定。也就是说,在int和string之间,没有最佳选择。编译器将始终使用true表达式的类型,并在必要时隐式转换false表达式。

    在第二个示例中:

    int? subscriptionID; // comes in as a parameter
    
    EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
    {
        Value = subscriptionID.HasValue ? (object)subscriptionID : DBNull.Value,
    }
    


    这不是所谓的“三元运算符”,而是 三元运算符,但称为“条件运算符”

        2
  •  15
  •   Eric Lippert    16 年前

    尽管其他答案是 ,从他们做出真实和相关的陈述的意义上说,这里有一些语言设计的微妙之处还没有被表达出来。许多不同的因素促成了当前条件运算符的设计。

    x.M(some-expression. 智能感知需要能够分析 一些表情 ,确定其类型,并在IntelliSense知道x.M所指的方法之前生成下拉列表。IntelliSense在看到所有参数之前无法确定M是否重载,但您甚至还没有输入第一个参数。

    void M(object x) {}
    void M(int x) {}
    void M(string x) {}
    ...
    M(b ? 1 : "hello");
    

    这该怎么办?它应该调用对象重载吗?它应该有时调用字符串重载,有时调用int重载吗?如果你有另一个超负荷,比如说 M(IComparable x) --你什么时候选?

    当类型信息“双向流动”时,事情变得非常复杂。说“我正在把这个东西分配给object类型的变量,因此编译器应该知道选择object作为类型是可以的”并不是wash;通常情况下 我们不知道您分配给的变量的类型,因为这正是我们正在试图弄清楚的

    http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-one.aspx

    第三,C#的一个微妙但一贯应用的设计原则是“不要用魔法生成类型”。当给出一个表达式列表时,我们必须从中确定类型, 我们确定的类型总是在列表的某个地方

    这种设计决策的原因是,它使普通人更容易计算出编译器在任何给定情况下将要做什么,其中必须确定最佳类型;如果你知道一种就在那里的类型,盯着你的脸,会被选中,那么你就更容易知道会发生什么。

    它还避免了我们在发生冲突时,必须制定大量复杂的规则,确定一组类型中最常见的类型。假设您有类型{Foo,Bar},其中两个类都实现IBlah,并且两个类都继承自Baz。哪一种是最好的通用类型,IBlah,它们都实现了,还是Baz,它们都扩展了?我们不想回答这个问题;我们想完全避免它。

    最后,我注意到C#编译器实际上在一些不太清楚的情况下对类型的判断有细微的错误。我的第一篇文章是:

    http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woes-part-one.aspx

    不管怎样,这只是设计三元运算符这个特殊方面的几个原因。这里还有其他微妙之处,例如,CLR验证器如何确定给定的分支路径集是否保证在所有可能的路径的堆栈上保留正确的类型。详细讨论那件事会使我走得很远。

        3
  •  2
  •   JaredPar    16 年前

    为什么特性X是这样的,这通常是一个很难回答的问题。回答实际行为要容易得多。

        4
  •  0
  •   James Bailey    16 年前

    http://msdn.microsoft.com/en-us/magazine/cc301569.aspx

    通常,由于性能损失难以追踪,应避免装箱。

    声明: 对象o=((1==2)?1.“测试”);

    1. #1中的最终类型是否与“对象o”的赋值运算符类型匹配?