公共常量是否“不好”?


38

这是:

public MyClass
{
    public const string SomeString = "SomeValue";
}

比这更糟:

public MyClass
{
    public static string SomeString { get{ return "SomeValue";}}
}

两者可以用相同的方式引用:

if (someString == MyClass.SomeString)
     ...

但是,第二个保护是作为财产的。但是,这真的比const好多少?

我已经学到了遍及公共领域的危险。因此,当我看到一些在公共字段上使用这些常量的代码时,我立即着手将其重构为属性。但是到了一半,我想知道拥有静态属性而不是常量有什么好处。

有任何想法吗?


1
以这种方式使用的公共常量就可以了。以这种方式使用属性是过大的。
伯纳德

2
您是否考虑过使用readonly关键字?ReadOnly为您提供了const的更简洁的syntanx,而没有许多帖子中提到的问题。
马特·拉夫

也可以做...公共静态只读类型constantName = 0;
史努比

Answers:


56

在C#中,由于该线程中提到的任何原因,这都是非常糟糕的。

C#中的公共常量被烘焙到引用程序集中。意思是,如果您在一个单独的程序集中有一个SomeOtherClass,它引用了MyClass中的SomeString,则为SomeOtherClass生成的CIL将包含一个硬编码的“ SomeValue”字符串。

如果您重新部署包含MyClass但不包含SomeOtherClass的dll并更改const,SomeOtherClass将不包含您认为会的内容-它将包含原始值。

如果您100%肯定是Pi等普适常数,那就疯了;否则要小心踩踏。

这是一个更好的解释:https : //stackoverflow.com/questions/55984/what-is-the-difference-between-const-and-readonly


3
@Oded,但const和只读属性之间存在相同的区别。const被烘焙到调用程序集中,不是只读属性。
svick 2012年

1
这是我不知道的。进一步的证据表明,公共领域是不好的。我认为即使是Pi的“安全”示例也是一个坏主意(当开发人员希望在Pi上获得更多或更少的精度时,又如何更改装配而又不知道这个问题。)我有40多个装配解决方案,如果我们不小心的话,我会发现这确实使我们感到痛苦。
瓦卡诺

2
这种“复制”是否会在C#的其他任何部分中发生?(即枚举)
Vaccano'2

2
是的,复制确实发生了。通常这不是问题,但是如果您的代码使用了Enum的数值,并且以该问题中概述的方式进行了更改,则可能会导致问题。
瓦卡诺

1
这是为什么constC#愚蠢的主要原因之一。我们需要对不可变对象的更好支持……
KChaloux

22

将字段更改为属性是一项重大更改。 您将失去二进制,源和反射兼容性。

此外:

  • 具有属性的更细粒度的访问控制。是否需要将其公开获取,但实际上只希望将其设置为受保护的访问权限?没问题(至少从C#2开始)。
  • 是否想在值更改时闯入调试器?只需在设置器中添加一个断点即可。
  • 是否要记录所有访问权限?只需将日志记录添加到吸气剂即可。
  • 属性用于数据绑定;字段不是。

http://csharpindepth.com/articles/chapter8/propertiesmatter.aspx

说了这么多,我看不出常量是如何真正受到此影响的(特别是如果您不需要上述任何功能),除非您的API更改为不再是常量。


11

事实上,公共领域的风险是可变的,并且其基础的实现可能会发生变化。

涉及到const这通常不是问题(类似于公共枚举)-除非您认为const最终会变成可变的,并且有时需要在访问器周围进行封装(例如记录它被查看了多少次)最高),您最好还是将其保留为公众const


1

常数就是数据。当您过多地“看”该值时,属性暗示了行为的可能性。

具有恒定数据的捆绑行为(或其将来的可能性)是完全错误的。对于大多数系统而言,这并不重要,但是可以。

可以说该值为“ PI”,并广泛用于系统的计算中。将其置于属性之后将迫使客户端程序员进行防御性编程。他们必须将值赋给重复的常量。如果他们不欺骗,则该库的下一个版本可能会在该属性后面引入一些不需要的“行为”。属性的行为(如果在编译的库中)是未知的。也许它在测试中表现良好,但是如果满足特殊条件,可能会有隐藏的代码执行。这不是过早的优化。尤其对于实时系统而言,人们的生活赖以生存。

客户端程序员甚至可能会失去常量的安全性,因为该语言可能不允许他们将属性值分配给其重复常量。

同样,当程序员被迫将您的属性值分配给自己的常量时,它们会有效地使您希望通过属性完成的任何行为无效。

真正的常数数据不需要或不需要封装。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.