[英]Declare a const array
是否可以編寫類似於以下內容的內容?
public const string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
是的,但您需要將其聲明為readonly
而不是const
:
public static readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
原因是const
只能應用於其值在編譯時已知的字段。 您展示的數組初始值設定項不是 C# 中的常量表達式,因此會產生編譯器錯誤。
將其聲明為readonly
可以解決該問題,因為該值直到運行時才會初始化(盡管它保證在第一次使用數組之前已初始化)。
根據您最終想要實現的目標,您還可以考慮聲明一個枚舉:
public enum Titles { German, Spanish, Corrects, Wrongs };
您可以將數組聲明為readonly
,但請記住,您可以更改readonly
數組的元素。
public readonly string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
...
Titles[0] = "bla";
考慮使用枚舉,如 Cody 建議的,或 IList。
public readonly IList<string> ITitles = new List<string> {"German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();
您不能創建“const”數組,因為數組是對象,只能在運行時創建,而 const 實體在編譯時解析。
您可以做的是將您的數組聲明為“只讀”。 除了可以在運行時設置值之外,這與 const 具有相同的效果。 它只能設置一次,此后它是只讀(即常量)值。
從 C# 6 開始,你可以這樣寫:
public static string[] Titles => new string[] { "German", "Spanish", "Corrects", "Wrongs" };
另請參閱: C#:新的和改進的 C# 6.0 (特別是“Expression Bodied Functions and Properties”一章)
這將創建一個只讀的靜態屬性,但它仍然允許您更改返回的數組的內容,但是當您再次調用該屬性時,您將再次獲得原始的、未更改的數組。
為了澄清起見,此代碼與(或實際上是其簡寫)相同:
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[] 並更改內容,如下所示:
((string[]) Titles)[1] = "French";
這是唯一正確的答案。 您目前無法執行此操作。
所有其他答案都建議使用類似於 的靜態只讀變量,但與常量不同。 常量被硬編碼到程序集中。 靜態只讀變量可設置一次,可能是在初始化對象時。
這些有時可以互換,但並非總是如此。
編輯:我想我會把這個扔進去,因為似乎問這個問題的人對數組有點模糊。 當您聲明一個數組時,它是一個指向包含該數組的內存段的指針。 它非常簡單,它只是一個地址,沒有復雜的邏輯控制它是否可讀或可寫。 它給了你一個指針,你可以用它做任何你想做的事。
這就是為什么制作不可變數組有點棘手的部分原因。 您可以編寫一個包裝數組的類,並且只允許通過返回副本來讀取它,但它實際上不再只是一個數組。
有些人建議使用 static 或 readonly 來模擬如果可以創建 const 數組時會看到的行為。 這些有一些副作用,對普通讀者來說可能並不明顯。
要真正獲得 const 數組,需要更新 C# 和 MSIL 底層代碼,以允許從數組讀取,但不允許寫入。
改進了tdbeckett 答案的.NET Framework v4.5+ 解決方案:
using System.Collections.ObjectModel;
// ...
public ReadOnlyCollection<string> Titles { get; } = new ReadOnlyCollection<string>(
new string[] { "German", "Spanish", "Corrects", "Wrongs" }
);
注意:鑒於集合在概念上是常量,在類級別將其聲明為static
可能是有意義的。
以上:
使用數組初始化屬性的隱式支持字段一次。
請注意{ get; }
{ get; }
- 即,只聲明一個屬性getter - 是什么使屬性本身隱式只讀(試圖將readonly
與{ get; }
結合實際上是一個語法錯誤)。
或者,您可以省略{ get; }
{ get; }
並添加readonly
創建領域,而不是一個屬性,如問題,但暴露公共數據成員的屬性,而不是場是一個好習慣的形成。
創建一個類似數組的結構(允許索引訪問),它是真正且健壯的只讀(概念上不變,一旦創建),兩者都涉及:
IReadOnlyList<T>
解決方案不同,其中(string[])
可用於獲得對元素的寫訪問權限,如mjepsen 的有用答案所示。IReadOnlyCollection<T>
接口,盡管名稱與類ReadOnlyCollection
相似,但它甚至不支持索引訪問,因此從根本上不適合提供類似數組的訪問。)如果你在 IReadOnlyList 接口后面聲明一個數組,你會得到一個在運行時聲明的具有常量值的常量數組:
public readonly IReadOnlyList<string> Titles = new [] {"German", "Spanish", "Corrects", "Wrongs" };
在 .NET 4.5 及更高版本中可用。
您可以采用不同的方法:定義一個常量字符串來表示您的數組,然后在需要時將該字符串拆分為一個數組,例如
const string DefaultDistances = "5,10,15,20,25,30,40,50";
public static readonly string[] distances = DefaultDistances.Split(',');
這種方法為您提供了一個常量,可以將其存儲在配置中並在需要時轉換為數組。
為了完整起見,現在我們還可以使用 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
為了我的需要,我定義了static
數組,而不是不可能的const
,它可以工作: public static string[] Titles = { "German", "Spanish", "Corrects", "Wrongs" };
這是一種做你想做的事情的方法:
using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
public ReadOnlyCollection<string> Titles { get { return new List<string> { "German", "Spanish", "Corrects", "Wrongs" }.AsReadOnly();}}
它與做一個只讀數組非常相似。
我相信你只能讓它只讀。
數組可能是只能在運行時評估的事物之一。 必須在編譯時評估常量。 嘗試使用“只讀”而不是“常量”。
作為替代方案,要解決只讀數組的元素可以修改問題,您可以改用靜態屬性。 (仍然可以更改單個元素,但這些更改只會在數組的本地副本上進行。)
public static string[] Titles
{
get
{
return new string[] { "German", "Spanish", "Corrects", "Wrongs"};
}
}
當然,這不會特別有效,因為每次都會創建一個新的字符串數組。
最佳選擇:
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 };
快速解決方法,以防它對某人有幫助。 我需要一個string[]
作為 Attribute 的參數(在某些理論中為測試用例傳遞內聯數據)。 readonly
在這里沒有幫助。 但是,我最終做了:
const string foo = "a|b|c";
[InlineData(foo)]
public void Test(string fooString)
{
var foo = fooString.Split("|"); // foo == {"a","b","c"}
...
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.