为什么我的类中不能有“public static const string S =“stuff”;”?

432

编译我的类时,我遇到了一个错误:

常量'NamespaceName.ClassName.CONST_NAME'无法标记为静态。

位于以下行:

public static const string CONST_NAME = "blah";

我在Java中一直都可以这样做。我做错了什么?为什么它不让我这样做?


2
好问题。为什么我们必须通过艰苦的方式来学习呢?编译器应该忽略静态并显示警告,以便我们知道(为什么)下次可以避免输入一些字符。 - frenchone
6个回答

775

const对象始终是static的。


4
const 使变量成为常量,不可更改。 - Samuel
7
@jinguy说:const 本质上就是静态的 —— 如果你有任何 const,它已经是静态的了,因此不需要也不能指定为静态。 - John Rudy
9
为什么?对于变量来说,readonly 实际上比 Java 的 final 更加灵活——你可以在构造函数中设置它多次,但其他地方不行。这非常方便。 - Jon Skeet
97
常量在编译时嵌入,并且在运行时不包含在静态类型对象中。静态变量不会被嵌入并且存在于类型对象内部。我之所以提到这一点,是因为没有人提到这种区别。 - user1228
4
它们仍然存在于执行时-例如,您可以使用反射(如GetField)来访问它们。 - Jon Skeet
显示剩余10条评论

123

来自C#语言规范(PDF第287页,或PDF的第300页):

尽管常量被视为静态成员,但常量声明既不要求也不允许使用static修饰符。


2
此内容也可在这里找到:http://msdn.microsoft.com/zh-cn/library/aa645749(VS.71).aspx - Lasse V. Karlsen

39

编译器认为const成员是静态的,同时意味着常量值语义,这意味着常量的引用可能会被编译进使用代码中,作为常量成员的值,而不是成员的引用。

换句话说,一个包含值为10的const成员,可能被编译为在代码中使用数字10,而不是const成员的引用。

这与一个始终被编译为对字段的引用的static readonly字段不同。

请注意,这是预JIT。当JIT编译器发挥作用时,它可以将这两个都编译为目标代码的值。


非常重要的一点是,编译后的代码假定常量值在未来版本中不会更改。 - PJTraill

8

C#中的const与Java中的final完全相同,唯一的区别是它始终是static。在我看来,一个const变量并不一定非得是非static的,但如果你需要以非static的方式访问const变量,可以这样做:

class MyClass
{    
    private const int myLowercase_Private_Const_Int = 0;
    public const int MyUppercase_Public_Const_Int = 0;

    /*        
      You can have the `private const int` lowercase 
      and the `public int` Uppercase:
    */
    public int MyLowercase_Private_Const_Int
    {
        get
        {
            return MyClass.myLowercase_Private_Const_Int;
        }
    }  

    /*
      Or you can have the `public const int` uppercase 
      and the `public int` slighly altered
      (i.e. an underscore preceding the name):
    */
    public int _MyUppercase_Public_Const_Int
    {
        get
        {
            return MyClass.MyUppercase_Public_Const_Int;
        }
    } 

    /*
      Or you can have the `public const int` uppercase 
      and get the `public int` with a 'Get' method:
    */
    public int Get_MyUppercase_Public_Const_Int()
    {
        return MyClass.MyUppercase_Public_Const_Int;
    }    
}

嗯,现在我意识到这个问题是4年前提出的,但是由于我花了大约2个小时的时间,尝试各种不同的回答方式和代码格式化,所以我仍然发布它。

但是,为了记录,在此我仍然感觉有点傻。


5
据我所知,Java中的final与C#中的readonly非常相似,而与const完全不同。 - Ben Voigt
@jjnguy 感谢您的编辑;我真的不知道为什么选择了那个原始措辞。 - Meowmaritus

7

来自MSDN:http://msdn.microsoft.com/en-us/library/acdd6hb7.aspx

...另外,虽然const字段是编译时常量,但readonly字段可用于运行时常量...

因此,在const字段中使用static就像试图在C/C++中定义静态一样...由于它在编译时被替换为其值,因此对于所有实例它只被初始化一次(= static)。


3

const与static相似,我们可以使用类名访问两个变量,但不同的是,静态变量可以修改,而常量不能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接