声明一个const数组

是否有可能写类似于以下的东西?

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

是的,但你需要声明它readonly而不是const

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

原因是const只能应用于编译时已知值的字段。 你显示的数组初始值设定项不是C#中的常量expression式,所以会产生编译器错误。

声明它readonly解决了这个问题,因为值直到运行时才被初始化(虽然它保证在第一次使用数组之前被初始化)。

根据你最终想要达到什么,你也可以考虑声明一个枚举:

 public enum Titles { German, Spanish, Corrects, Wrongs }; 

您可以将数组声明为readonly ,但请记住,您可以更改readonly数组的元素。

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

考虑使用枚举,如科迪build议,或IList。

 public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly(); 

你不能创build一个'const'数组,因为数组是对象,只能在运行时创build,而const实体在编译时parsing。

你可以做的是将你的数组声明为“只读”。 这与const的效果相同,除了可以在运行时设置该值。 它只能被设置一次,并且是一个只读(即const)值。

你可以采取一种不同的方法:定义一个常量string来表示你的数组,然后当你需要的时候把string拆分成一个数组

 const string DefaultDistances = "5,10,15,20,25,30,40,50"; public static readonly string[] distances = DefaultDistances.Split(','); 

这种方法给你一个常量,可以存储在configuration中,并在需要时转换为数组。

阿拉斯泰尔

为我的需要我定义static数组,而不是不可能的const ,它的工作原理: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

从C#6开始,你可以这样写:

 public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" }; 

另请参阅: C#:新增和改进的C#6.0 (特别是“expression式主体函数和属性”一章)

这将使一个只读的静态属性,但它仍然会允许你改变返回的数组的内容,但是当你再次调用属性,你会得到原来的,不变的数组了。

澄清,这个代码是相同的(或实际上是一个简写):

 public static string[] Titles { get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; } } 

请注意,这种方法有一个缺点:新的数组实际上是在每个引用上实例化的,所以如果你使用的是一个非常大的数组,那么这可能不是最有效的解决scheme。 但是如果你重新使用相同的数组(例如把它放在一个私有属性中),它将再次打开改变数组内容的可能性。

如果你想有一个不可变的数组(或列表),你也可以使用:

 public static IReadOnlyList<string> Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" }; 

但是,这仍然有变化的风险,因为您仍然可以将其转换回string[]并更改内容,如下所示:

 ((string[]) Titles)[1] = "French"; 

.NET Framework v4.5 +解决scheme改进了tdbeckett的答案 :

 using System.Collections.ObjectModel; // ... public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>( new string[] { "German", "Spanish", "Corrects", "Wrongs" } ); 

注意:鉴于集合在概念上是恒定的,在级别声明它可能是有意义的。

以上:

  • 使用数组初始化属性的隐式后台字段

    • 请注意{ get; } { get; } – 即只声明一个属性getter – 是什么使属性本身隐式只读(试图结合readonly{ get; }实际上是一个语法错误)。

    • 或者,你可以忽略{ get; } { get; }并添加readonly来创build一个字段,而不是一个属性,在问题中,但暴露公共数据成员作为属性而不是字段是一个好习惯形成。

  • 创build一个类似于数组的结构 (允许索引访问),这个结构是真正强健的只读 (概念上,常量,一旦创build)

    • 防止对集合进行修改(例如通过删除或添加元素,或者将集合replace为整体)
    • 防止修改个别元素。
      (即使是间接修改也是不可能的 – 与IReadOnlyList<T>解决scheme不同的是,可以使用(string[]) 强制转换来获取对元素的写入权限,如mjepsen的有用答案所示 。
      同样的漏洞也适用于IReadOnlyCollection<T>接口,尽pipe名字与 ReadOnlyCollection相似,但它甚至不支持索引访问,使得它基本上不适合提供类似数组的访问)。

这是一种做你想做的事的方法:

 using System; using System.Collections.ObjectModel; using System.Collections.Generic; public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}} 

这和做一个只读数组非常相似。

我相信你只能使它只读。

数组可能是那些只能在运​​行时进行评估的事情之一。 常量必须在编译时进行评估。 尝试使用“只读”而不是“const”。

另外,为了解决只读数组中的元素可修改问题,可以使用静态属性来代替。 (单个元素仍可以更改,但这些更改只能在数组的本地副本上进行。)

 public static string[] Titles { get { return new string[] { "German", "Spanish", "Corrects", "Wrongs"}; } } 

当然,每次创build一个新的string数组时,效率都不是很高。

如果你在IReadOnlyList接口后面声明一个数组,你会得到一个在运行时声明的具有常量值的常量数组:

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

在.NET 4.5和更高版本中可用。