2013-03-21 19 views
12

私はC#コードで宣言する必要がある長いバイト配列を持っています。私はこのような何か:長い定数バイト配列の宣言

public static class Definitions 
{ 
    public const byte[] gLongByteArray = new byte[] { 
     1, 2, 3, 
     //and so on 
    }; 
} 

をしかし、私はconstの配列のみをヌルで初期化することができるというエラーが発生します。

私はstaticconstを変更する場合、それはコンパイルが、私は持っている問題はこれです - 私はpublic static byte[] gLongByteArrayとしてそれを宣言するとき、それは私のアプリをロードするたびに初期化されることはありません、右?その場合、gLongByteArray変数は、メモリにロードされるコンパイル済みのexe/dllファイルで定義されている配列を指しています。理由は私はこの配列がかなり長いので、私は私のプログラムは、アプリケーションが起動するたびに、それを読み込んでCPUサイクルを無駄にしたくない、または悪い、このクラスは参照されている...

+0

このような場合でもパフォーマンスの影響は最小限に抑えられます。より大きな問題は、 'byte []'が定数であるための非常に良い候補ではないということです。変わらないものには定数を使用することをお勧めしますが、将来の実装ではバイトシーケンス(特に長いバイトシーケンス)がうまく変更される可能性があります。 'const'を使用すると、コンパイラは定数へのすべての参照を 'ベークイン'します。これは、定数値がコード全体で_duplicated_であることを意味します。後で定数を変更すると、新しい定数に対してコンパイルされたモジュールだけが新しい値を持ちます。 –

+1

他の人が言っているように、推測に基づいてパフォーマンスの決定を下さないでください。事実に基づいてそれらを作る。現実的なサイズの配列を作成し、起動時のパフォーマンスを測定します。その後、効果があるかどうかがわかります。定数で初期化された大きなバイト配列は、合理的に効率的に処理されます。 –

+0

@EricLippert:デバッガについて聞いたことはありませんか? – ahmd0

答えて

26

コンパイル時定数constキーワードで宣言されたもの)は厳しく制限されています。そのような定数を得るためにはコードを実行しないでください。そうでなければ、コンパイル時定数にすることはできません。 constのデフォルト値はstaticです。あなたは定数を作成したいとあなたはコンパイル時の定数を使用できない場合

、あなたの代わりにstatic readonlyを使用することができます。

public static readonly byte[] longByteArray = new byte[] { 1, 2, 3, 4, 5 }; 

staticキーワードは、それが一度だけ初期化されることを保証し、宣言する型の一部(各インスタンスではありません)。 readonlyキーワードは、longByteArray変数をその後変更することはできません。

Definitions.longByteArray = new byte[] { 4, 5, 6 }; // Not possible. 

警告:タイプではない配列が、読み取りを行い、それを防ぐために

Definitions.longByteArray[3] = 82;     // Allowed. 

:上記のコードでは、私ははまだこれを行うことができますので、配列は、可変ですIEnumerable<T>またはIReadOnlyList<T>などのコレクション専用インターフェイス、またはキャストによって変更することを許可しないReadOnlyCollection<T>などの読み取り専用のコレクションタイプがさらに優れています。

public static readonly IReadOnlyList<byte> longByteArray = new byte[] { 1, 2, 3, 4, 5 }; 
+0

良い答えですが、サンプルは 'byte a = 82974;でコンパイルされません;はコンパイル時エラーです。 –

+0

@AlexeiLevenkov良いキャッチ。私はちょうどいくつかの乱数を思いついた。 :P – Virtlink

+0

IReadOnlyLIstの最後の例でも、それをバイト[]にキャストして配列の値を変更できます。ご覧のとおり[こちら](https://gist.github.com/jcmcbeth/00aee115b6ec18de617729e4e40af655)。それがリストであれば、最後にAsReadonly()を使うことができます。 – jcmcbeth

3

配列をconstにしてください。 documentationによると:クラス、構造体、およびアレイを含む

ユーザー定義タイプは、constことができません。

あなたはもちろん、この

public static class Definitions 
{ 
    public static readonly byte[] gLongByteArray = new byte[] { 
     1, 2, 3, 
     //and so on 
    }; 
} 

のような静的な読み取り専用フィールドとして、それを宣言する必要があるだろう、このように、実行時に、あなたの配列要素をoverwrittingから誰かを停止することは何もありません。

Definitions.gLongByteArray[0] = 0xFF; 

あなたは@Virtlinkが示唆することをコレクションに建てられたのいずれかを使用するか、その(example)を防止するために、独自のカスタム読み取り専用配列クラスを作成する必要があると思います。

0

最初にアプリケーションをロードすると、静的クラスが初期化されます。特に問題があると判断していない限り、パフォーマンスについて心配しないでください。

+3

技術的には、静的初期化は、クラスが参照される方法/時間に応じて、可変時間に発生します。これはめったに問題ではありませんが、それは知る価値があります。フィールドを参照するまでに少なくとも実行されていることが保証されています。 –

0

すべてのコンテンツをファイルに書き込んで、リソースとして埋め込みます!