声明一个const数组

时间:2011-02-28 13:04:57

标签: c# .net arrays const readonly

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

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

15 个答案:

答案 0 :(得分:595)

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

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

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

声明它readonly解决了这个问题,因为该值在运行时才初始化(尽管它保证在第一次使用数组之前已经初始化)。

根据您最终想要实现的目标,您可能还会考虑声明枚举:

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

答案 1 :(得分:51)

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

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

考虑使用enum,如Cody建议的那样,或IList。

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

答案 2 :(得分:41)

你不能创建'const'数组,因为数组是对象而且只能是 在运行时创建,const实体在编译时解析。

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

答案 3 :(得分:10)

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

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

另请参阅:C# : The New and Improved C# 6.0(特别是章节&#34;表达身体功能和属性&#34;)

这将创建一个只读的静态属性,但它仍然允许您更改返回的数组的内容,但是当您再次调用该属性时,您将再次获得原始的,未改变的数组。

为澄清起见,此代码与(或实际上是简写)相同:

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

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

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

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

但是,这仍然存在更改的风险,因为您仍然可以将其转换回字符串[]并更改内容,如下所示:

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

答案 4 :(得分:9)

这是唯一正确的答案。您目前无法执行此操作。

所有其他答案都建议使用静态只读变量,这些变量与 类似,但与常量不同。将常量硬编码到程序集中。静态只读变量只能设置一次,可能是在对象初始化时完成的。

这些有时可以互换,但并非总是如此。

答案 5 :(得分:6)

您可以采用不同的方法:定义一个常量字符串来表示您的数组,然后在需要时将该字符串拆分为数组,例如。

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

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

阿拉斯泰尔

答案 6 :(得分:5)

根据我的需要,我定义了static数组,而不是不可能的const并且它有效: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };

答案 7 :(得分:5)

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

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

适用于.NET 4.5及更高版本。

答案 8 :(得分:3)

这是一种做你想做的事情:

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

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

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

答案 9 :(得分:3)

tdbeckett's answer上改进的 .NET Framework v4.5 +解决方案

using System.Collections.ObjectModel;

// ...

public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
  new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);

注意:假设集合在概念上是不变的,那么让它static级别声明它是有意义的。

以上:

  • 使用数组初始化属性的隐式支持字段一次

    • 请注意{ get; } - 即,仅声明属性 getter - 是使属性本身隐式只读的原因(尝试将readonly{ get; }结合使用{1}}实际上是语法错误。)

    • 或者,你可以省略{ get; }并添加readonly来创建字段而不是属性,就像在问题中一样,但是暴露 public 数据成员作为属性而非字段是一种很好的习惯。

  • 创建一个 array- ,如结构(允许索引访问真实且健壮的只读< / strong>(概念上恒定,一旦创建),两者都与:

    • 阻止整个集合的修改 (例如删除或添加元素,或者为变量指定新集合)。
    • 阻止修改个别元素 (即使间接修改也是不可能的 - 与 IReadOnlyList<T> 解决方案不同,其中 a (string[])强制转换可用于获得对元素的写访问权,如mjepsen's helpful answer所示 相同的漏洞适用于 IReadOnlyCollection<T> 界面 ,尽管名称与 class ReadOnlyCollection相似,但< strong>甚至不支持索引访问,这使得它从根本上不适合提供类似阵列的访问。)

答案 10 :(得分:2)

我相信你只能把它变成只读。

答案 11 :(得分:1)

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

答案 12 :(得分:1)

为了完整起见,现在我们还有ImmutableArrays供我们使用。 这应该是真正不变的:

public readonly static ImmutableArray<string> Tiles = ImmutableArray.Create(new[] { "German", "Spanish", "Corrects", "Wrongs" });

需要System.Collections.Immutable NuGet参考

https://msdn.microsoft.com/en-us/library/mt452182(v=vs.111).aspx

答案 13 :(得分:1)

最佳选择:

public static readonly byte[] ZeroHash = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

答案 14 :(得分:0)

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

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

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