是否可以写下类似于以下内容的内容?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
答案 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"};
}
}
当然,这不会特别有效,因为每次都会创建一个新的字符串数组。