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

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

当前回答

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

using System.Collections.ObjectModel;

// ...

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

注意:假定集合在概念上是常量,在类级别声明它时将其设置为静态可能是有意义的。

上面的:

Initializes the property's implicit backing field once with the array. Note that { get; } - i.e., declaring only a property getter - is what makes the property itself implicitly read-only (trying to combine readonly with { get; } is actually a syntax error). Alternatively, you could just omit the { get; } and add readonly to create a field instead of a property, as in the question, but exposing public data members as properties rather than fields is a good habit to form. Creates an array-like structure (allowing indexed access) that is truly and robustly read-only (conceptually constant, once created), both with respect to: preventing modification of the collection as a whole (such as by removing or adding elements, or by assigning a new collection to the variable). preventing modification of individual elements. (Even indirect modification isn't possible - unlike with an IReadOnlyList<T> solution, where a (string[]) cast can be used to gain write access to the elements, as shown in mjepsen's helpful answer. The same vulnerability applies to the IReadOnlyCollection<T> interface, which, despite the similarity in name to class ReadOnlyCollection, does not even support indexed access, making it fundamentally unsuitable for providing array-like access.)

其他回答

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

using System.Collections.ObjectModel;

// ...

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

注意:假定集合在概念上是常量,在类级别声明它时将其设置为静态可能是有意义的。

上面的:

Initializes the property's implicit backing field once with the array. Note that { get; } - i.e., declaring only a property getter - is what makes the property itself implicitly read-only (trying to combine readonly with { get; } is actually a syntax error). Alternatively, you could just omit the { get; } and add readonly to create a field instead of a property, as in the question, but exposing public data members as properties rather than fields is a good habit to form. Creates an array-like structure (allowing indexed access) that is truly and robustly read-only (conceptually constant, once created), both with respect to: preventing modification of the collection as a whole (such as by removing or adding elements, or by assigning a new collection to the variable). preventing modification of individual elements. (Even indirect modification isn't possible - unlike with an IReadOnlyList<T> solution, where a (string[]) cast can be used to gain write access to the elements, as shown in mjepsen's helpful answer. The same vulnerability applies to the IReadOnlyCollection<T> interface, which, despite the similarity in name to class ReadOnlyCollection, does not even support indexed access, making it fundamentally unsuitable for providing array-like access.)

这是唯一正确的答案。目前还不能这样做。

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

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

编辑:我想我应该把这个扔进来,因为似乎问这个问题的人对数组有点模糊。声明数组时,它是指向包含该数组的内存段的指针。它非常简单,因为它只是一个地址,没有复杂的逻辑控制它是否可读或可写。它给你一个指针,你可以用它做任何你想做的事情。

这就是为什么创建一个不可变数组有点棘手的部分原因。你可以写一个包装数组的类并且只允许通过返回一个副本来读取它,但这样它就不再只是一个数组了,它是一个包装数组的对象。

有些人建议使用static或readonly来模拟创建const数组时看到的行为。这些药物有一些副作用,对普通读者来说可能不太明显。同样,如果你用readonly标记一个数组,你是在标记指向数组的指针,而不是数组本身。你可以随心所欲地改变数组的内容:

public class Demo
{
    private readonly int[] _foo = new int[] {0,1,2,3};
    
    public void ChangeArray()
    {
        _foo[1] = 42; // works
        _foo = new int[] { 0, 1, 2, 3, 5 }; // won't even compile
    }
}

要真正获得const数组,需要对c#和MSIL底层代码进行更新,以允许从数组中读取,但不允许写入。本页上的其他建议是解决这个问题的各种创造性方法。

我相信你只能让它只读。

为了我的需要,我定义了静态数组,而不是不可能的const,它工作: 公共静态字符串[]title ={"德语","西班牙语","纠正","错误"};

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

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

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

它非常类似于做一个只读数组。