声明一个const数组

是否可以编写类似于以下内容的内容?

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

#1楼

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


#2楼

您可以采取另一种方法:定义一个常量字符串来表示您的数组,然后在需要时将其拆分为一个数组,例如

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

这种方法为您提供了一个常量,可以将其存储在配置中,并在需要时转换为数组。


#3楼

这是一种执行所需操作的方法:

using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;

public ReadOnlyCollection Titles { get { return new List { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}

这与执行只读数组非常相似。


#4楼

作为替代方案,要解决带有只读数组的元素可能被修改的问题,可以改用static属性。 (仍可以更改各个元素,但是这些更改将仅在数组的本地副本上进行。)

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

当然,这并不是特别有效,因为每次都会创建一个新的字符串数组。


#5楼

从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";

#6楼

.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相似,但它甚至不支持索引访问 ,从而从根本上不适合提供类似数组的访问。)

#7楼

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

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

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


#8楼

我相信您只能将其设为只读。


#9楼

数组可能是只能在运行时评估的事物之一。 常量必须在编译时求值。 尝试使用“只读”而不是“常量”。


#10楼

是的,但是您需要声明为readonly而不是const

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

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

将其声明为readonly可解决该问题,因为该值要到运行时才会初始化(尽管可以保证在第一次使用该数组之前就已对其进行了初始化)。

根据最终要实现的目标,您还可以考虑声明一个枚举:

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

#11楼

您无法创建'const'数组,因为数组是对象,只能在运行时创建,而const实体则在编译时解析。

您可以做的是将数组声明为“只读”。 除了可以在运行时设置值之外,这与const具有相同的作用。 它只能设置一次,此后是只读(即const)值。


#12楼

您可以将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();

#13楼

为了完整起见,现在我们还可以使用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

你可能感兴趣的:(声明一个const数组)