是否可以编写类似于以下内容的内容?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
对于我的需要,我定义了static
数组,而不是不可能的const
,它可以工作: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
您可以采取另一种方法:定义一个常量字符串来表示您的数组,然后在需要时将其拆分为一个数组,例如
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
这种方法为您提供了一个常量,可以将其存储在配置中,并在需要时转换为数组。
这是一种执行所需操作的方法:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection Titles { get { return new List { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
这与执行只读数组非常相似。
作为替代方案,要解决带有只读数组的元素可能被修改的问题,可以改用static属性。 (仍可以更改各个元素,但是这些更改将仅在数组的本地副本上进行。)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
当然,这并不是特别有效,因为每次都会创建一个新的字符串数组。
从C#6开始,您可以这样编写:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
另请参见: C#:新增和改进的C#6.0 (特别是“表达式主体功能和属性”一章)
这将创建一个只读静态属性,但仍允许您更改返回的数组的内容,但是当再次调用该属性时,您将再次获得原始的,未更改的数组。
为了澄清起见,此代码与(或实际上是以下简称)相同:
public static string[] Titles
{
get { return new string[] { "German", "Spanish", "Corrects", "Wrongs" }; }
}
请注意,这种方法有一个缺点:实际上,每个引用上都会实例化一个新数组,因此,如果您使用的是非常大的数组,这可能不是最有效的解决方案。 但是,如果您重复使用同一数组(例如,通过将其放入私有属性中),将再次打开更改数组内容的可能性。
如果您想要一个不可变的数组(或列表),也可以使用:
public static IReadOnlyList Titles { get; } = new string[] { "German", "Spanish", "Corrects", "Wrongs" };
但是,这仍然存在更改的风险,因为您仍然可以将其强制转换回string []并更改内容,例如:
((string[]) Titles)[1] = "French";
.NET Framework v4.5 +解决方案 ,改进了tdbeckett的回答 :
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection Titles { get; } = new ReadOnlyCollection(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
注意:鉴于集合在概念上是常量,因此在类级别将其声明为static
可能是有意义的。
以上:
使用数组一次初始化属性的隐式后备字段 。
注意{ get; }
{ get; }
-即,仅声明属性getter-是使属性本身隐式只读的原因(尝试将readonly
与{ get; }
实际上是语法错误)。
另外,您也可以省略{ get; }
{ get; }
并添加readonly
以创建一个字段而不是一个属性,就像在问题中那样,但是将公共数据成员公开为属性而不是字段是一种良好的习惯。
创建一个类似于数组的结构 (允许索引访问 ),该结构真正且健壮地为只读 (概念上是常量,一旦创建),就以下方面而言:
IReadOnlyList
解决方案不同,在IReadOnlyList
解决方案中, 可以使用(string[])
强制转换 获得对元素的写访问权限 ,如mjepsen的有用答案所示 。 IReadOnlyCollection
接口 ,尽管其名称与类 ReadOnlyCollection
相似,但它甚至不支持索引访问 ,从而从根本上不适合提供类似数组的访问。) 如果在IReadOnlyList接口后面声明一个数组,则将获得一个在运行时声明的具有常量值的常量数组:
public readonly IReadOnlyList Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
在.NET 4.5及更高版本中可用。
我相信您只能将其设为只读。
数组可能是只能在运行时评估的事物之一。 常量必须在编译时求值。 尝试使用“只读”而不是“常量”。
是的,但是您需要声明为readonly
而不是const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
原因是const
只能应用于其值在编译时已知的字段。 您显示的数组初始值设定项在C#中不是常量表达式,因此会产生编译器错误。
将其声明为readonly
可解决该问题,因为该值要到运行时才会初始化(尽管可以保证在第一次使用该数组之前就已对其进行了初始化)。
根据最终要实现的目标,您还可以考虑声明一个枚举:
public enum Titles { German, Spanish, Corrects, Wrongs };
您无法创建'const'数组,因为数组是对象,只能在运行时创建,而const实体则在编译时解析。
您可以做的是将数组声明为“只读”。 除了可以在运行时设置值之外,这与const具有相同的作用。 它只能设置一次,此后是只读(即const)值。
您可以将array声明为readonly
,但请记住,可以更改readonly
array的元素。
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
根据Cody的建议,考虑使用enum或IList。
public readonly IList ITitles = new List {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
为了完整起见,现在我们还可以使用ImmutableArrays。 这应该是真正不变的:
public readonly static ImmutableArray Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });
需要System.Collections.Immutable NuGet参考
https://msdn.microsoft.com/zh-CN/library/mt452182(v=vs.111).aspx