【发布时间】:2011-08-22 20:38:21
【问题描述】:
我读到 C# 允许将局部常量初始化为空引用,例如:
const string MyString = null;
但是这样做有什么意义吗?这有什么可能的用途?
【问题讨论】:
-
考虑到可能有多种用途,我认为这没有明确的答案。因此,它可能应该是一个社区 wiki。
标签: c# string reference null constants
我读到 C# 允许将局部常量初始化为空引用,例如:
const string MyString = null;
但是这样做有什么意义吗?这有什么可能的用途?
【问题讨论】:
标签: c# string reference null constants
例如,如果您使用常量来配置您的应用程序,那为什么不呢? null 值可以代表一个有效的状态——例如没有安装记录器。另请注意,当您声明一个局部常量时,您可以将其初始化为全局常量给定的值(这可能是一个更有趣的场景)。
编辑: 另一个问题是,在什么情况下使用const 有什么好处?对于配置,您可能希望配置文件和其他变量通常会更改(除非它们是不可变的,但 readonly 更适合...)
【讨论】:
const。该示例假定 logger 是一个在运行时不会更改的全局设置。
public/internal/private String const ErrorMessage = "Library Fault";
确实,您可以将本地const 字符串和readonly 引用类型初始化为null,尽管这似乎是多余的,因为它们的默认值无论如何都是null。
然而,null 是一个编译时常量,足以初始化字符串和引用类型。因此,编译器必须竭尽全力来考虑、识别和拒绝这种特殊情况,即使从语言的角度来看它仍然完全有效。
这样做的好处是有争议的,而且一开始可能不值得付出努力。
【讨论】:
null”的情况。还有更多,我的意思是有时,即使一个特殊情况似乎没有意义,但为了支持更一般的情况,仍然值得保留它的行为。
如果你想编写没有关键字的代码,如果你喜欢的话,可以使用它:
const string UninitializedSetting = null;
if (mySetting == UninitializedSetting)
{
Error("mySetting string not initialized");
}
【讨论】:
我的猜测是因为 null 是一个有效值,可以分配给引用类型和可为空的值类型。 我看不出有什么理由禁止这样做。
可能存在一些非常有用的极端情况,例如多目标和条件编译。 IE 您想为一个平台定义一个常量,但由于缺少功能而在另一个平台上将其定义为 null。
例如,可能有用的用法:
#IF (SILVELIGHT)
public const string DefaultName = null;
#ELSE
public const string DefaultName = "Win7";
#ENDIF
【讨论】:
选择命名一个值(而不是使用就地魔术常数)、使用const 和设置为null 或多或少是正交问题,尽管我同意维恩图可能有一个非常小的三者的重叠区域:)
我能想到的一种情况是,当您拥有与编写代码一样多或更多的一次性数据时,但您希望确保在编写或维护代码时不会意外更改这些值。这种情况在单元测试中相当常见:
[Test]
public void CtorNullUserName()
{
const string expectedUserName = null;
var user = new User(expectedUserName);
Assert.AreEqual(expectedUserName, user.Name, "Expected user name to be unchanged from ctor");
}
您可以通过不涉及将null 分配给const 的多种方式构建此类代码,但这仍然是一个有效的选择。
这也可能有助于解决方法重载问题:
public class Something
{
public void DoSomething(int? value) { Console.WriteLine("int?"); }
public void DoSomething(string value) { Console.WriteLine("string"); }
}
// ...
new Something().DoSomething(null); // This is ambiguous, and won't compile
const string value = null;
new Something().DoSomething(value); // Not ambiguous
【讨论】:
除了已经指出的情况之外,它可能与 C# 语言的一个怪癖有关。 C# 规范 3.0,第 8.5.2 节指出:
局部常量声明的类型和常量表达式必须遵循与常量成员声明相同的规则(第 10.4 节)。
10.4 以内的内容如下:
如第 7.18 节所述,常量表达式是可以在编译时完全计算的表达式。由于创建除字符串之外的引用类型的非空值的唯一方法是应用 new 运算符,并且由于常量表达式中不允许使用 new 运算符,因此引用类型常量的唯一可能值字符串以外的为空。
【讨论】: