如何定义字符串常量而不是数组

3
在C#中,您可以定义一个“const string”,但不能定义数组,因为数组是对象。据我了解,字符串实际上是对象,因为它们是传递值的引用对象,就像数组一样。
那么我们如何做到这一点:
const string NewLine = "\r\n";

但不包括这个:
const byte[] AesSwapBytes = new byte[] { ... };

是因为我们不能在字符串上更改单个字符 (NewLine[0] = '\n'),但可以在数组上更改 (arr[0] = i) 吗?


3
您可以将字符串声明为常量,因为字符串可以使用字面值(像其他可用作字面值或属性的类型一样)创建和表示。您不能定义一个字面数组,但可以实例化一个。 - Jeff Mercado
2
@Sam,你可以重新分配只读数组的值。 - Cole Tobin
2
@DJKRAZE:在C#(或.NET)中,不存在动态数组这样的东西。那只是一个恰好为空的集合初始化器。在这种情况下创建的数组是一个长度为0的字符串数组。不能动态增加大小,它是固定的。但是,您可以使用尽可能多的值进行初始化。但是,您得到的只是一些编译器魔法,生成指令以创建n长度的数组,并将每个n值设置在数组的相应位置上。 - Jeff Mercado
1
@DJKRAZE,我同意Jeff的观点。根据你上面的评论(string[] dynamicArray = {}),这并不会创建一个"动态数组",而只是创建了一个固定大小的空数组。一旦数组被创建,就无法改变其大小。你所能做的就是创建另一个数组并复制数据。 - Thomas Levesque
可能是声明一个常量数组的重复问题。 - Cole Tobin
显示剩余7条评论
4个回答

2
无论变量是对象还是结构体,都与其是否可以被声明为const无关。要使变量成为const,需要将赋值语句右侧设置为编译时字面量。只有少数类型具有编译时字面量,如stringintdouble和其他数字类型。正如另一个答案中提到的,null是编译时字面量,因此如果确实需要,可以将任何可空类型分配为const并将其赋值为null(尽管这并没有什么用处)。如果C#添加了编译时字面量(除了null)导致数组,则可以创建有意义的const数组。在那之前,您将需要使用其他机制来完成所需操作。

1

根据这篇MSDN文章,在C#中可以定义一个readonly数组。C#特别不允许您将数组声明为constant,因为赋值表达式不是常量。

public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

然而,第一条评论详细说明了这种方法有点无用,因为

您不能重新分配数组,但可以替换单个值。

在Stack Overflow上有更多信息


这并不是无用的,因为了解数组类型字段是否始终指向相同的数组实例通常很重要。另外,如果变量始终指向同一个数组,则在ReadOnlyCollection中包装数组将产生一个“活动”的只读视图,但如果该字段稍后引用不同的数组,则会产生错误。那些不理解持有对象和持有引用之间区别的人可能会被readonly标识符所困惑,但那些理解这种区别的人将认识到它的重要性。 - supercat
@supercat,我指的是数组并不像我们通常期望的“只读”,因为它实际上是可变的。 - David B
很遗憾,C#语法中的 readonly int[] Foo 看起来像是一个整数只读数组,而不是vb样式的 ReadOnly Foo As Integer(),后者更像是声明对整数数组的只读引用,但了解C#和.net的人应该明白声明承诺了什么以及没有承诺什么; 任何无法理解此内容的人可能会在理解 Array1 = Array2Array1 = (int[])Array2.Clone()Array.Copy(Array1, Array2, Array1.Length);之间的差异时出现其他重大问题。 - supercat

1

实际上,只要初始化程序是编译时常量,您就可以使用const关键字声明数组常量。

const byte[] Nothing = null;

通常情况下,对于引用类型,只有null是编译时常量。

.NET有一个特殊的例外,也允许字符串字面量。


2
这真是无用的。谁会这样做? - Cole Tobin
2
@BenVoigt 我认为字符串并不是一个例外;只是它们可以表示为字面量,而数组则不能... 而 null 之所以有效是因为它是一个字面量。 - Thomas Levesque

1

readonly 声明的数组问题在于,即使该字段是只读的(您无法将其引用到另一个数组),数组本身的内容仍然可以更改。

如果您需要一个“不可变数组”,其中您无法更改内容,则答案是:不要使用数组数组是可变的,您无法做任何事情来改变它。

一个可能的解决方法是使用只读集合:

static readonly IList<byte> AesSwapBytes =
    new ReadOnlyCollection<byte>(new byte[] { ... });

如果您需要将其用作数组,只需在其上调用ToArray扩展方法。它将返回一个带有数据副本而非原始数组的数组;因此,如果您修改ToArray的结果,它不会影响原始集合。

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