実につまらない場所で手が止まったのでメモ。
C# 4.0のデフォルト引数にはどのような値でも格納できるわけではなく、メタデータに格納できる値しか入りません。実行時に確定する値は格納できません。当然、readonlyのフィールド値(例Color.Empty)も使用できません。readonlyは初期化後に変更できないだけで、初期化時に値を変更できてしまうからです。(しかも、リフレクションで強引に書き換えることまでできてしまう)
さて問題は、System.Draw.Color構造体でEmptyの値を無効扱いしていた場合です。クラスインスタンス引数にnullを渡すのと同じように、Emptyを渡して無効を示したいわけです。しかし、構造体はnullになりません。
しかし、構造体はdefault(T)またはnew T()を引数に渡せます。
問題は、default(T) == new T() == Emptyかという点です。
検証プログラム §
using System;
using System.Drawing;
class Program
{
private static void sample(string name,Color a = default(Color))
{
Console.WriteLine("{0} is ARGB=({1},{2},{3},{4})",name,a.A,a.R,a.G,a.B);
}
static void Main(string[] args)
{
sample("by default parameter");
sample("by Empty parameter",Color.Empty);
Console.WriteLine(Color.Empty == default(Color));
Console.WriteLine(Color.Empty == new Color());
}
}
結果 §
by default parameter is ARGB=(0,0,0,0)
by Empty parameter is ARGB=(0,0,0,0)
True
True
結論 §
Color.Emptyとdefault(Color)またはnew Color()の値は交換可能と思って良さそうです。
感想 §
Color.Emptyをあまりに使い慣れていたので、new Color()で同じ値が得られるとは思ってもいなかたなあ。まして、default(Color)。デフォルト引数にColor.Emptyを書こうと思わなかったら、永遠に見落としたままだったかも。考えてみればこの結果は当たり前なのだけど。