読者です 読者をやめる 読者になる 読者になる

変数の型と格納されているオブジェクトの型

.NET

どちらかというと DSL よりもこちらが本題だったりしますが.
引数に渡されたオブジェクトがシリアライズ可能かどうか判定するために,以下のようなコードを書いたとします.ここでは簡単のために Serializable 属性についてのみを考えることにしましょう.

static public bool IsSerializable1<T>(T obj)
{
    Type t = typeof(T);
    return t.IsDefined(typeof(SerializableAttribute), false);
}

static public bool IsSerializable2<T>(T obj)
{
    Type t = obj.GetType();
    return t.IsDefined(typeof(SerializableAttribute), false);
}

2つのコードの違いが分かりますでしょうか? 前者は変数の型で,後者は格納されているオブジェクトの型で判断しています.
BCL のシリアライザは,変数の型ではなく格納されているオブジェクトの型が Serializable 属性を持つかどうかをチェックします.例えば極端な例として,フィールドが全て System.Object 型のクラスを考えてみると分かりやすいでしょう.このクラスがシリアライズ可能かどうかは,実行して見るまで分かりません.
もっとも,実際のところ怖いのはクラス定義からは一見「シリアライズ可能」に見えるフィールドに,シリアライズ不可能なオブジェクトが格納されているというパターンでしょう.Serializable は Inherited = false とされているため,基底クラスが Serializable 属性を持つからといって,派生クラスが Serializable 属性を持つとは限りません.
このようにある型のフィールドをスキャンするようなコードを書くときには,フィールド変数の型に興味があるのか格納されているオブジェクトの型に興味があるのか注意するようにしましょう.(追記:NonSerializedAttribute 等フィールドそのものに付与される属性も重要なので注意.)