【问题标题】:operator for enums枚举运算符
【发布时间】:2011-01-28 11:07:26
【问题描述】:

只是出于好奇,问这个

像下面的表达式一样

a = (condition) ? x : y; // two outputs

为什么我们不能有一个枚举运算符?
说,

myValue = f ??? fnApple() : fnMango() : fnOrange(); // no. of outputs specified in the enum definition

而不是 switch 语句(即使重构是可能的)


enum Fruit
{
    apple,
    mango,
    orange      
};

Fruit f = Fruit.apple;

还是某种无用的算子?

【问题讨论】:

  • 除了混淆之外,我没有看到这一点。 (基于布尔表达式选择结果出现了很多,但不是枚举。)

标签: c# enums operators ternary-operator


【解决方案1】:

主要问题 - 除了在大多数实际情况下不安全、不必要和可能不可读之外 - 是它促进了一种现在大多数人认为不好的编程模型。

大多数语言都有它们允许并想要推广的编程/设计风格。 C# 允许命令式和过程式编程,但促进了面向对象技术的使用。您的运算符坚定地属于第一阵营,并且不是该语言的设计者想要支持的东西。

如果您确实想以这种风格进行编程,那么您可以使用:

    myValue = (f == Fruit.apple) ? fnApple() 
            : (f == Fruit.mango) ? fnMango()
            : fnOrange();

【讨论】:

    【解决方案2】:

    我能想到三个原因:

    1. 它很脆。如果有人决定重新排序枚举,那么您最终会调用错误的函数。
    2. 这不是显而易见的。如果不切换到枚举定义并检查枚举的顺序,我无法理解在哪种情况下会运行哪个函数。
    3. Every feature starts with minus 100 points. 这样的事情不太可能证明规范、构建、记录和测试它所需的努力是合理的,尤其是与其他功能相比时,尤其是当语言中已经存在高度可行的替代方案时.

    【讨论】:

      【解决方案3】:

      我不能说我曾经想要这样一个运算符 - 如果依赖枚举值的顺序,它会变得非常脆弱。您可以轻松使用开关:

      switch (f)
      {
          case Fruit.Apple: myValue = fnApple(); break;
          case Fruit.Mango: myValue = fnMango(); break;
          case Fruit.Orange: myValue = fnOrange(); break;
          default: throw new ArgumentOutOfRangeException("f");
      }
      

      或者,创建一个地图:

      static readonly Dictionary<Fruit, Func<Foo>> FruitFunctions = 
          new Dictionary<Fruit, Func<Foo>> {
          { Fruit.Apple, fnApple },
          { Fruit.Mango, fnMango },
          { Fruit.Orange, fnOrange }
      };
      ...
      
      myValue = FruitFunctions[f]();
      

      我在各种情况下都使用了这两种技术,恐怕我更喜欢它们而不是建议的运算符。

      【讨论】:

      • 为什么我们不能依赖他们的订单?
      • @Veer 您可以稍后添加一个,然后您必须更改所有使用 ???操作员。使用地图,您只需在一处修改即可。
      • @Veer:两点 - 首先,订单在使用时不可见,因此难以阅读。其次,枚举声明中看似无害的更改将完全改变代码的含义。
      • @Veer:我想说,当操作员脆弱或缺乏可读性的辩护是“你不会经常使用它”时,这说明了一切;)
      • @Veer:当操作符那么脆弱时,这绝对是 C# 团队不将其包含在语言中的标志。没有高附加值。相反,另一种方式是在脚下开枪。
      【解决方案4】:

      条件被评估为真或假。您不存在的运算符的建议算法是什么?很难说它是否有用,但 switch-case 可以做你需要的。

      【讨论】:

      • 我不明白你的第一个问题。你能改写一下吗?
      【解决方案5】:

      C# 借用 C++ 的语法,C++ 借用 C 的语法,而 C 没有 ???::: 运算符,因为 K&R 可能觉得没有必要。它不是一个“无用的运算符”,但它会被视为语法糖。

      此外,运算符依赖枚举声明中常量的特定顺序并不是一个好主意。

      【讨论】:

      • C 和 C++ 没有运算符本身并不是一个好的理由——它们也没有 lambda 表达式或空合并运算符。有更好的 other 理由不拥有它,例如您最后一句话中的理由。更重要的是,没有充分的理由拥有它 IMO。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-04
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 1970-01-01
      相关资源
      最近更新 更多