【问题标题】:Why can't nullables be declared const?为什么不能将 nullables 声明为 const?
【发布时间】:2009-12-02 15:18:32
【问题描述】:
[TestClass]
public class MsProjectIntegration {
    const int? projectID = null;
    // The type 'int?' cannot be declared const
    // ...
}

为什么我没有const int?

编辑: 我想要一个可以为空的 int 作为 const 的原因是因为我只是用它来从数据库加载一些示例数据。如果它为空,我将在运行时初始化示例数据。这是一个非常快速的测试项目,显然我可以使用 0 或 -1 但int? 只是感觉就像我想做的正确的数据结构。 readonly 似乎是要走的路

【问题讨论】:

  • 我真的想不出你需要一个值为空的常量的情况。可以请教一下吗?
  • 最佳实践:仅对逻辑上永远不变的事物使用常量。好:一打中的物品数量,猫王出生的年份,铅的原子序数。坏:版本号——它们从一个版本到另一个版本;变化的东西不应该是常数。糟糕:当前日元兑欧元汇率;每秒都在变化。
  • 是的,我基本上只是将它用作临时配置文件,绝对不是最佳实践
  • 那不应该是“是的,非常好!我基本上是……” 幽默>

标签: c# null constants nullable


【解决方案1】:

这不仅仅是可空值;只有运行时内置的类型可以声明为const(从内存中,它是布尔值、各种类型的 int、浮点数/双精度数和字符串)。

为什么?因为值在编译时直接嵌入到程序集中,并且无法嵌入用户定义的类型。

不过,readonly 关键字应该可以满足您的需求。与const 相比,任何readonly 字段都在运行时而不是编译时进行初始化,因此可以使用或多或少的任何您想要的表达式来初始化它们。

编辑:正如 Eric Lippert 指出的那样,事情并非如此简单。例如,const decimal 有效。

这个:

private const decimal TheAnswer = 42;

...编译(嗯,反射器)到这个:

[DecimalConstant(0, 0, (uint) 0, (uint) 0, (uint) 42)]
private static readonly decimal TheAnswer;

【讨论】:

  • 谢谢,组装部分很有启发性,使这成为(对我来说)最好的答案
  • 这是不正确的。首先:小数不是内置类型,但它们可以是 const。第二:是的,有办法嵌入常量用户定义类型;我们选择不实现此功能。原则上当然可能。 (证明:我们是为十进制做的。)
  • 哈哈,当我问这个问题时,我没想到 c# 编译器团队的人会做出回应
  • 这是 stackoverflow 如此糟糕的原因之一。
  • 有人想知道是什么让“allowed as const”列表中的项目如此特别;除了 String 之外的其他不可变类型应该完全可以用作 const。喜欢颜色和日期时间;毕竟,这两者基本上也只是一个裸 int 的包装器(分别是 Int32 和 Int64)。
【解决方案2】:

http://en.csharp-online.net/const,_static_and_readonly

常量必须是整数类型 (sbyte, 字节, 短, ushort, int, uint, long, ulong, 字符, 浮点数, double、decimal、bool 或 string)、一个 枚举,或对 null 的引用。

由于类或结构是 在运行时用新的初始化 关键字,而不是在编译时,你 无法为类设置常量或 结构。

既然 nullable 是一个结构体,那么上面的引用就是原因。

【讨论】:

    【解决方案3】:

    你不能有一个 const 引用类型(或一个结构),因此你不能有一个 const int?这实际上只是一个Nullable<int>.

    您可以将其标记为只读

    readonly int? projectID = null;
    

    那么就不能在类构造函数之外修改了。

    【讨论】:

    • Nullable<T> 不是引用类型,而是结构。 ;)
    【解决方案4】:

    您可能需要考虑使用“只读”修饰符。

    consts 在编译时评估,而readonlys 在运行时强制执行。复杂类型的实例无法编译到程序集中,因此必须在运行时创建。

    【讨论】:

    • Nullable<T> 不是引用类型,而是结构。 ;)
    【解决方案5】:

    你基本上是在说:

    我有一个带有 projectId 字段的类 可能有也可能没有价值,但是 事实上,它从来没有价值,它是 始终未定义。

    从逻辑的角度来看……声明本身没有意义。

    【讨论】:

    • 因为它的配置设置可能为空,我宁愿不围绕一个幻数进行编码....比如 -1
    • 如果 projectId 是“const”,你就不能从数据库中加载任何东西......事实上你几乎不能用它做任何事情。
    • 主键如何为空?
    • var project = projectID.HasValue ? Project.GetProjectByID(projectID.Value, connectionString) : new Project();
    • 当然有道理。例如,在使用 DataRowAttribute 的单元测试中。我想声明我的测试数据,比如 private const int? NullStudentId = null;私人 const int ZeroStudentId = 0;私人 const int ValidStudentId = 100;然后在 [DataRow] 中使用我的常量(不能使用只读必须是常量),例如 [DataRow[NullStudentId)] [DataRow(ZeroStudentId)] [DataRow(ValidStudentId)] 不幸的是我不能这样做。我需要使用 null 而不是 NullStudentId。这是 const int 的一种有效用法?
    猜你喜欢
    • 2011-06-03
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 2018-08-15
    • 1970-01-01
    相关资源
    最近更新 更多