为什么不能将结构声明为const?

时间:2011-01-04 05:04:58

标签: c# struct stack const

4 个答案:

答案 0 :(得分:39)

因为值类型构造函数可以执行任何 - 例如,根据一天中的时间切换逻辑。常量值类型在理智上是有意义的,但由于构造函数可以灵活地做任何他们喜欢的事情,它在实践中根本不能用于自定义值类型。 (请记住,常量是在编译时计算的,,这意味着你的构造函数必须在编译时运行。)

答案 1 :(得分:21)

C#中的Const意味着可以在编译时确定 ,这就是为什么只有非常原始的类型如intstring才能成为const。

如果您来自C背景,readonly关键字可能更适合您。

答案 2 :(得分:4)

我刚用一个简单的可变结构测试了readonly关键字:

struct Test
{
   public int value;

   public void setInt(int val)
   {
      value = val;
   }
}

static class Program
{
   public static readonly Test t = new Test();

   static void Main()
   {
      Console.WriteLine(t.value); // Outputs "0"
      t.setInt(10);
      //t.value = 10;  //Illegal, will not let you assign field of a static struct
      Console.WriteLine(t.value); // Still outputs "0"
   }
}

即使readonly结构在技术上不是编译时常量,运行时也不会让它发生变化。即使是踩到setInt()方法,它看起来像值更改,但不显示Main中的更改。

我猜结构本身被置于“只读”内存中,不允许它们改变。不像一个只保持指针不变的类,允许类字段本身随意改变。

所以看起来static readonly有效const,即使对于可变结构也是如此。

答案 3 :(得分:3)

要使C#编译器生成结构类型的const值,它必须知道应该在其所有字段中使用哪些值。 C#编译器本质上知道如何初始化某些类型的字段,如Decimal,但对于大多数值类型,它没有这样的知识。

编译器有可能提供一种在所有struct字段都被暴露的上下文中声明结构类型的常量值的方法。如果结构的字段是private,那么该类型的常量只能在结构中声明;如果字段是internal,则常量可以在程序集中的任何位置声明;如果public,可以在任何地方声明它们。

虽然我希望看到这样的功能,但我不希望任何主流的.net语言实现它。编译器固有地知道的命名常量类型可以参与其他常量表达式,而static readonly变量则不能。如果NumRows是一个等于4的常量,则Arr[3*NumRows+7]之类的表达式可以替换为Arr[19],即使在外部程序集中定义了NumRows也是如此。这使得这些常数比static readonly变量具有显着的优势。但是,如果常量是编译器本身不能识别的类型,那么参与任何常量表达式的能力非常有限,从而有效地否定了它作为常量的优点。如果值类型常量具有公开字段,则编译器可以将该字段的值用作常量,但由于.net语言的创建者在逻辑上与具有公开字段的结构相对,我不会指望他们即使可以允许这样使用。

static readonly变量上有一些潜在的用例支持常量,但是许多这样的情况可以使用现有类型来处理。例如,库可能会公开const Int64以编码有关其版本的信息,并将该值用作GetLinkedVersionInfo方法的默认参数值。在编译时,有问题的值将被“烘焙”到调用代码中,从而允许该方法报告调用者链接的库的版本,并可能确定它正在运行的版本是否存在任何兼容性问题。