【问题标题】:Does Conditional attribute eliminate subexpressions too?条件属性是否也消除了子表达式?
【发布时间】:2013-07-31 09:20:13
【问题描述】:

我有 C/C++ 背景。我通常在我的代码上放置大量断言,而在 C 或 C++ 中,没有保证可以消除对作为断言参数的子表达式的评估。所以我不得不使用宏。

在 C# 中,我没有那种级别的宏支持。但我有Conditional 属性。根据我使用 C 和 C++ 的经验,由于副作用,子表达式无法被消除。

例如,

[Conditional(DEBUG)]
void func1(int a)
{
    //  Do something.
}
int func2()
{
    //  Will this be called?
}

func1(func2());

如果func2 仍然被调用,我应该像isDebugMode() && func1(func2()) 这样编码。但这是我真正想要避免的。所以我想知道Conditional 属性是否保证消除子表达式。

如果没有,编写调试构建断言的最佳实践是什么,它将在发布构建时完全剥离?

AFAIK,这是编译器特定的支持。我想知道Mono编译器的情况。

【问题讨论】:

    标签: c# mono conditional-compilation


    【解决方案1】:

    func2 不会被调用。在 C# 语言规范中有说明,因此 Mono 编译器必须按照这些规则行事。

    MSDNhttp://msdn.microsoft.com/en-us/library/aa664622(v=vs.71).aspx:

    Conditional 属性启用条件的定义 方法。 Conditional 属性通过测试 条件编译符号。对条件方法的调用是 包含或省略取决于是否定义了此符号 在通话点。如果定义了符号,则调用是 包括;否则,调用 (包括对参数的评估) 调用)被省略。

    【讨论】:

      【解决方案2】:

      func2() 不会被调用,因为对func1() 的调用将被完全删除。

      如果您打算将此功能用于断言,您可能需要考虑使用Code Contracts

      您将能够添加参数验证和其他断言,这些断言可以选择从发布版本中完全剥离(有一个后处理器进行剥离)。

      要验证参数,您可以执行以下操作:

      public void Test(int value)
      {
          Contract.Requires((0 < value) && (value < 10));
          // ...
      }
      

      你可以这样断言条件:

      Contract.Assume(something != 0);
      

      【讨论】:

        【解决方案3】:

        线

        func1(func2());
        

        如果 DEBUG == false 将被删除

        【讨论】:

          【解决方案4】:

          c# 中也有宏,但它们与 c++ 不同。

          您可以在Conditional Compilation Symbols 中声明一个宏并像这样检查它们

          #if MACRO
          #endif
          

          Here你可以阅读他们的文档。

          希望对你有帮助。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-07-12
            • 1970-01-01
            • 2016-02-23
            • 1970-01-01
            • 2017-07-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多