【问题标题】:Why would this compile?为什么会编译?
【发布时间】:2012-08-15 16:25:08
【问题描述】:

我为之前在我的代码中多次明确声明的值创建了一个“const”:

private static readonly int QUARTER_HOUR_COUNT = 96;

当我对 QUARTER_HOUR_COUNT 进行 96 的搜索和替换时,我无意中也替换了声明,所以它变成了:

private static readonly int QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT;

...但它已编译。我认为这将不允许这样做。为什么它被编译器接受为有效声明?

【问题讨论】:

标签: c# constants


【解决方案1】:

我认为它不允许这样做。为什么它被编译器接受为有效声明?

大概是因为语言规范允许这样做。您认为语言规范中是否有特定的规则禁止它?

如果您的问题真的是“为什么语言规范不禁止这样做” - 我怀疑这是因为可能很难确保您禁止您真正想要禁止的事情,而实际上禁止所有此类事情。

您可能会争辩说,对于 simple 直接赋值给自身的情况,最好在语言规范中有一个特殊情况,但它会为 的语言引入复杂性相对收益不大。

请注意,即使您没有收到错误,我也希望您收到警告 - 如下所示:

Test.cs(3,33):警告 CS1717:对同一变量进行了赋值;你的意思是指派别的东西吗?

另请注意,如果您将其设为const 而不仅仅是静态只读变量,那么您确实会收到编译时错误:

Test.cs(3,23): error CS0110: 'Program.QUARTER_HOUR_COUNT' 常量值的评估涉及循环定义

另请注意,根据 .NET 命名约定,这应该称为 QuarterHourCount,而不是 SHOUTY_NAME。

【讨论】:

  • 未赋值变量的使用我会想到。
  • @leppie:不适用于静态字段初始化程序中的静态字段。术语“未赋值变量”与静态字段无关,静态字段没有明确赋值的概念。
  • @leppie:有一个初始化顺序,但没有不同的“未分配变量”概念。如果您认为它实际上违反了规则,您能否指出您认为它违反了规范的确切部分?
  • @JonSkeet:有趣;p 我们有一个隐藏的 Y 组合子!例如static Func<int, int> f = x => (x == 0) ? x : f(x-1);
  • @Jon:是的,我确实收到了那个警告信息,但我没有看到它,因为(至少在我设置 VS 的方式上)它不会显示,除非我通过 View | 明确查找错误列表。至于“shouty”这个名字,我意识到这是一个有争议的话题,我当然尊重你的意见,但这是我反对的风格趋势之一,因为当我浏览代码; IOW,shouty == 常量或“伪常量”(只读静态)
【解决方案2】:

代码生成的IL代码是这样的:

 IL_0007:  ldsfld     int32 Example.Quat::QUARTER_HOUR_COUNT//Load the value of a static field on the stack
 IL_000c:  stsfld     int32 Example.Quat::QUARTER_HOUR_COUNT// Store the value from the stack in the static field

由于 QUARTER_HOUR_COUNT 的默认值为 0,因此将 0 分配给 QUARTER_HOUR_COUNT

【讨论】:

    【解决方案3】:

    因为变量被初始化为0,然后设置为自身。

    我的猜测是它会在设置为自身之前执行一个 new Int() ,这会将其初始化为零。

    【讨论】:

      【解决方案4】:

      因为编译器会将这一行分解:

      private static readonly int QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT;
      

      基本上转化为IL等价于:

      private static readonly int QUARTER_HOUR_COUNT;
      QUARTER_HOUR_COUNT = QUARTER_HOUR_COUNT;
      

      然后显然这也会被更多地分解,但以上应该足以说明我的观点。

      所以从技术上讲,它会在使用时默认值为零。

      【讨论】:

        【解决方案5】:

        由于其他隐含值类型(如 int)具有默认值,因此声明变量而不显式初始化它意味着它仍然具有值。

        您可以像这样找出任何类型的默认值:

        int i = default(int);
        

        或更笼统地说:

        T t = default(T);
        

        请注意,对于引用类型,默认值为null,只有值类型才有默认值。

        【讨论】:

          猜你喜欢
          • 2010-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-03-24
          • 2021-12-17
          • 2015-01-03
          • 2020-08-23
          相关资源
          最近更新 更多