【问题标题】:?: Operator return void?: 运算符返回 void
【发布时间】:2012-11-04 07:58:25
【问题描述】:

我想使用?: 运算符而不是if else

例如

var directory = new DirectoryInfo(path);
if (!directory.Exist())
{
    directory.Create();
}
else 
{
    // do nothing
}

我尝试像这样使用?:

var directory = new DirectoryInfo(path);
!directory.Exist() ? directory.Create() : void;

但它说“无效的表达式术语void”,null 也不起作用。

谁能告诉我一个解决方案?

【问题讨论】:

  • 如果你没有“if 和 else”,你不需要(也不应该)使用三元运算符,或者你不需要返回值。它不会让执行更快,也不会让你看起来很专业,只会让你的代码变得混乱。

标签: c# .net operators


【解决方案1】:

在您的场景中,只有 if 条件更适合。

只是为了您的理解,三元运算符(?:)需要在右侧产生一个值,并且还需要在左侧分配一个变量来分配结果值例如:

    x =  (y== null) ? 0: 1;

这意味着当y is null 时将0 分配给x,否则分配1

因此,在您的示例/场景中,您可以编写类似这样的内容,从而导致目录创建状态如下:

    var newDirectoryCreated = (!directory.Exist()) ? directory.Create() : false;

这样,如果创建了新目录,则newDirectoryCreated 将分配true,否则分配false

【讨论】:

  • 如果他们实际上并不需要布尔状态?然后它只是弄乱了代码。 =)
  • @J.Steen: OP 已经用if 编写了代码,所以我只是提供了?: 运算符不工作的原因的答案,并且可以让它工作(更多来自学习看法)。我将在顶部添加注释。
【解决方案2】:

只需保留 if 语句并删除 else 类,因为您没有在其中执行任何操作。

您正在尝试使用ternary operator,根据定义,它必须返回一个值。

来自文档:

条件运算符 (?:) 根据布尔表达式的值返回两个值之一。

【讨论】:

  • 这解决了问题,但没有解释为什么他的代码不起作用。
【解决方案3】:

如果你只是想简洁,你可以试试这个:

if (!directory.Exist())
    directory.Create();

【讨论】:

    【解决方案4】:

    三元运算符并非旨在取代if/else,它们是为了简化赋值和声明。它应该能够将语句的结果分配给变量或函数之类的东西。主要用于作业或阅读。

    类似

    var status = !directory.Exist() ? directory.Create() : false;
    

    正确的解决方案是坚持原生if 条件。以下就足够了:

    var directory = new DirectoryInfo(path);
    if (!directory.Exist())
    {
        directory.Create();
    }
    

    【讨论】:

    • 它不会“什么都不做”。如果目录不存在(或者,如果已编译),它将创建目录
    • @jalf,告诉我void 会做什么。
    • 好吧,就像我说的,如果它编译了。重点是directory.Create() 肯定不会什么都不做
    • 可以更短:var status = directory.Exist() || directory.Create();
    【解决方案5】:

    ?: 操作符的行为大致是这样的:

    对于x ? y : z,如果x为真则返回y,否则返回z

    由此我们可以推断出几件事:

    • yz 都必须返回 something(如果它们中的任何一个评估为 void,它就不起作用),并且
    • yz 必须评估为 same 类型。 (想象一下你有这样的东西:var r = x ? y : z;。r 是哪个类型?是y 还是z 的类型?我们不知道它们中的哪一个会被返回,但我们必须在编译时。所以它们必须返回相同的类型。

    在您的情况下,两者都评估为void,这是行不通的。 (如果您将最后一部分更改为null,正如您所说您已经尝试过,那么它们会评估为不同的类型,其中一种是无效的,这违反了两个规则)

    【讨论】:

    • 是的,我在想... ? directory.Create() : null,因为 OP 说这是他尝试过的事情之一。澄清一点
    【解决方案6】:

    conditional operator (?:) 必须根据布尔表达式的值返回两个值之一。所以你可以坚持使用if 子句代替,它仍然很容易理解而不是条件运算符:

    var directory = new DirectoryInfo(path);
    if (!directory.Exist()) directory.Create();
    

    【讨论】:

      【解决方案7】:

      ?: 运算符是 if-then-else 结构的扩展。

      扩展在then-block和else-block中。如果 then 块和 else 块为 if-then-else 构造返回 void,它必须为 ?: 运算符返回一个类型。 ?: 运算符中类型的另一个约束是这两种类型必须相同。由于编译器将使用自动转换来使这两种类型相同,这一限制被稍微软化了。

      使用 ?: 运算符的代码通常更短,但也更难阅读。这是用 ?: 运算符替换 if-then-else 结构时要考虑的一点。除非您的 then-block 和 else-block 是一个衬垫,否则很少值得用 ?: 运算符替换它。

      if-then 结构是 if-then-else 结构的受限版本(反之亦然,if-then-else 结构是 if-then 结构的扩展)。由于 if-then 结构只有一个代码块,即 then-block,因此无法用 ?: 运算符替换 if-then 结构。您首先必须使用空的 else 块来扩展 if-then 结构。

      例子:

      // initialising an integer with an if-then construct.
      int x = 0;
      if (some_condition)
      {
          x = 1;
      }
      

      把这个想象成 then 块返回一个整数。 不能使用 ?: 运算符。

      // initialising an integer with an if-then-else construct.
      int y;
      if (some_condition)
      {
          y = 1;
      }
      else
      {
          y = 0;
      }
      

      将 if-then 构造扩展为 if-then-else 构造,并将 then-block 和 else-block 视为返回一个整数,以表示类型一致 ;-) 彼此匹配。 在这种情况下可以使用 ?: 运算符。

      // initialising an integer with a ?: operator.
      int z = (some_condition) ? 1 : 0;
      

      关于您的代码:

      var directory = new DirectoryInfo(path);
      if (!directory.Exist())
      {
          directory.Create();
      }
      

      在这种情况下,我看不到使 then 块返回值的明智方法。这使得使用 ?: 运算符变得不可能或非常复杂,因此代码丑陋。我的建议是,在这种情况下坚持使用 if-then 构造。

      【讨论】:

        猜你喜欢
        • 2016-01-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-09
        • 2017-03-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多