它们是堆栈上的不可变值类型。什么阻止我让他们成为一个常量?
参考文献:
答案 0 :(得分:39)
因为值类型构造函数可以执行任何 - 例如,根据一天中的时间切换逻辑。常量值类型在理智上是有意义的,但由于构造函数可以灵活地做任何他们喜欢的事情,它在实践中根本不能用于自定义值类型。 (请记住,常量是在编译时计算的,,这意味着你的构造函数必须在编译时运行。)
答案 1 :(得分:21)
C#中的Const意味着可以在编译时确定 ,这就是为什么只有非常原始的类型如int
和string
才能成为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
方法的默认参数值。在编译时,有问题的值将被“烘焙”到调用代码中,从而允许该方法报告调用者链接的库的版本,并可能确定它正在运行的版本是否存在任何兼容性问题。