constもreadonlyも定数だけど、その挙動は大きく違う。
基本的にはstatic readonlyを使おう。
本当にその定数が将来的に変更されない(円周率PIとか)ならconstを使っても良い。
###cosntって何?
- const = コンパイル時定数
- int,float,double,bool,char,stringの型が使える。
- 宣言時に値を代入する必要がある。
- string型が使えるので参照型も使えるのかも!と思ったけど、参照型でconstできるのはstringのみ
- プロパティをconstで定義することはできない。
- newを使えない
- constを使った定数にstaticキーワードをつけることはできない。
- static readonlyより早いらしい
- コンパイルされる時に定数の値と同じ値に置き換えられる
- switch文にも使える
Eric Lippertによれば、そもそもそのような状況はあってはならないもので、将来変更され得るような値をconst定義すべきではありません。円周率や金の原子に含まれる陽子の数のような、絶対不変の値のみがconst定義されるべきものである
http://ja.stackoverflow.com/questions/6653/const-と-static-read-only-の違いと使い分けについて
もう少しくだけて説明すると、const変数は自分が作ったアセンブリをクラスライブラリとして配布してしまうと、constの値を変えた場合は、それを使う側のアプリはリビルドしなければ反映されません。dll差し替えだけでは反映されないので注意。
http://ja.stackoverflow.com/questions/6653/const-と-static-read-only-の違いと使い分けについて
public const string a = "1";
public const string aa = null;//null代入はok
public const int b = 1;
public const bool c = true;
public const float d = 0.0f;
public const double e = 0.0d;
public const string a; //宣言時に値が代入されていない!
public const int b;//宣言時に値が代入されていない!
const string a = new string ('a', 1); //newは使えない!
public const Hoge hoge = new Hoge ();//参照型はstring以外は使えない
public const int AAA {//プロパティは使えない
get;
set;
}
public const int? c = null;//null許容型はだめ
public const string? d = null;//null許容型はだめ
public const static int f = 1;//staticキーワードは使えない
また宣言時に計算処理を使って代入できる。ただし処理に使えるのは値かconst定数だけ!
public const int a = 1;
public const int b = a + 1;
public const int c = b + 1;
public const int c = b + 1;//上の方にb+1しててもOK
public const int a = 1;
public const int b = a + 1;
public const int a = 1 + d; //dはconst定数じゃないから処理できない!
public const int b = 1 + e; //eはconst定数じゃないから処理できない!
public const int c = 1 + f; //fはconst定数じゃないから処理できない!
int d = 10;
public static readonly int e = 10;
public readonly int f = 10;
もちろんフィールド,コンストラクタ,メソッド内で自由に宣言可能!
あとスコープが違えば名前がかぶっていてもOK
public class Test
{
const int a = 1; //名前が同じでもOK
//コンストラクタ
public Test ()
{
const int a = 1; //コンストラクタ内でも宣言OK
}
public void Method1 ()
{
const int a = 1; //メソッド内でも宣言OK
}
public static void Method2 ()
{
const int a = 1; //static メソッド内でも宣言OK
}
}
int b = 1;
switch (b) {
case a:
break;
case 2:
break;
default:
break;
}
###constの速さ
結論:計測できず・・・
void Start ()
{
check ();
}
const int a = 1;
void check ()
{
int b;
Profiler.BeginSample ("const");
for (int i = 0; i < 100000; i++) {
b = a;
}
Profiler.EndSample ();
}
10万回constの値を取得した時に0.37ms ~ 0.5msほどかかった。
しかし、これだと変数bに代入する処理にかかる時間も含まれてしまうので、以下のコードで変数bに代入するのにかかる処理時間を計測する。
public class Test :MonoBehaviour
{
void Start ()
{
check ();
}
const int a = 1;
void check ()
{
int b;
Profiler.BeginSample ("const");
for (int i = 0; i < 100000; i++) {
b = 1;
}
Profiler.EndSample ();
}
}
これの計測結果も0.38ms ~ 0.51msと出てしまった。うーん、、、const使用時に実際に何秒かかるかはわからない。
それもそのはずで、const定数は、コンパイルされる時に定数の値と同じ値に置き換えられるため、
for (int i = 0; i < 100000; i++) {
b = a; //aはconst定数
}
上記のコードは以下に置き換えられます。
for (int i = 0; i < 100000; i++) {
b = 1;
}
なので両者の処理時間の違いは計測できないのです。
###static readonlyって何?
static readonly = 実行時変数
- これも定数扱い(読み取り専用)
- 値型にも参照型にも使える
- 宣言時に代入しなくてもエラーにはならない
- 宣言した後は代入できない
- readonlyだけならコンストラクタ内で初期化可能
- switch文に使えない
- constより本当に若干遅い(がきにするほどのレベルじゃない)
static readonly int a = 1;
static readonly string b = "1";
static readonly Hoge c = new Hoge (); //参照型もOK
static readonly int d; //代入しなくてもOK.1が入る
static readonly Hoge e; //代入しなくてもOK.Nullが入る
void Start ()
{
d = 100; //代入できない
}
static readonly int d;
public class Test2
{
public Test2 ()
{
a = 100;
}
readonly int a;
}
void AAA ()
{
int b = 100;
switch (b) {
case a:
break;
default:
break;
}
}
static readonly int a = 100;