XML の読み書きをしているコードを見る機会がありまして色々と調べたところ、モヤモヤした気持ちになったので、皆さんに共有します。
XmlSerializer を使っているとき DefaultValueAttribute で指定した値のときは XML に書き込まれない
見出しのタイトルの通りなのですが、XmlSerializer を使っていて、DefaultValueAttribute で指定している初期値の値になっている要素はXMLに書き出しされません。
例えば、シリアライズするクラスに Title というプロパティがあって、Title プロパティ の初期値は default title
が必ずセットされるとします。さらに、 DefaultValue
属性で初期値を明記してXMLの要素として読み書きできるようにしておきます。
[DefaultValue("default title")]
[XmlElement("title")]
public string Title { get; set; } = "default title";
ここで、 XmlSerializer を使ってシリアライズするタイミングで Title
の値が初期値の default title
だった場合、XMLに書き込まれません。
この挙動は、昔から知られていたようです。既ににこういった記事があります。
うーん、実に気持ちが悪い挙動です。[DefaultValue]で指定した値と同じときに、XMLに書き込まれないなんて属性名から想像できません。
これは単にバグで、仕様ではないのでは?と思い、調べてみると公式に「オプション機能だよ」と言ってそうな文章を見つけました。(訳が微妙で、英語の元文も自分は分かりにくかったので、本当にオプションだと言っているかは自信はありません)
これがオプションだって言われても納得できていない自分がいます…
DefaultValueAttribute
そもそも、DefaultValueAttribute 自体が誤解されやすそうだと思います。DefaultValueAttribute は初期値のセット自体はやってくれません。
ビジュアルデザイナーやコードジェネレーター用に使う物のようです。
わざわざ「!注意」があるので、勘違いする人も多いのでしょう。
さらに公式にはこんなページがありました。
はい。分かりにくいです(笑)。
そしてこの分かりにくい DefaultValueAttribute と XmlSerializer を組み合わせることで「DefaultValueAttribute で指定した値のときは XML に書き込まれない」という、さらなる挙動を「オプション」として提供してくれているわけです。
DefaultValueAttribute のページにはビジュアルデザイナーやコードジェネレーター用に使う物のような記述があるのに、 XmlSerializer と一緒に使う場合には属性の役割(目的)が変わっているような気がして実にモヤっとします。
という、モヤっとした動きのお話しでした。