tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルDeserialize で未設定値とそれ以外を区別する方法
記事No11532
投稿日: 2015/11/25(Wed) 21:19
投稿者たかし
#あいまいな説明になってしまうかもしれませんが、ご容赦ください。

<SampleClass 〜〜〜〜〜>
  <Person>
    <Name>たかし</Name>
    <Year>17</Year>
  </Person>
  <Person>
    <Name>よーこ</Name>
  </Person>
  <Person>
    <Name>たろう</Name>
    <Year>0</Year>
  </Person>
<SampleClass>

Name は必須。 Year は任意項目のようなイメージです。
これを Deserialize で以下のクラスに読み込みます。

Public Class Sample
  <〜〜〜〜
  Public Person As List(Of Person)
End Class

Public Class Person
  Public Name As String
  Public Year as Integer
End Class

そうした場合、よーこの Year は未定義なので、
読み込んだ際も未定義(を表すような値 Nothing など)にさせたいのですが、
Integer 型を使用している為にデフォルト値 0 となってしまいます。
(当然と言えば当然かもしれませんが…)
結果として、上記 xml の場合に、よーこもたろうも 0 となってしまいます。

このような場合に、数値を扱う際に
xml上、未定義なのか、あるいは本当にゼロという値が定義されているのか
区別する良い方法はありませんでしょうか?

[ツリー表示へ]
タイトルRe: Deserialize で未設定値とそれ以外を区別する方法
記事No11533
投稿日: 2015/11/26(Thu) 09:00
投稿者Hongliang
XmlSerializerの話と言うことで良いですかね?

このままでは、XML上に限らず、プログラム上でも未定義なのかどうか識別できないと思うのですが。
旧来良くある手法としては、決して使用しない値(-1だとか&H7FFFFFFFだとか)を未定義値として扱うという手があります。
.NET 2.0以降追加されたNullableを使えば、数値とnull(Nothing)を扱うことが可能になります。この場合、XmlSeralizerは既定では属性xsi:nil="true"を持った空要素として表現します。
XML上に-1やらxsi:nil="true"やらが出現するのが困るのであれば、IXmlSerializableを実装してその辺の挙動を調整することもできます。

[ツリー表示へ]
タイトルRe^2: Deserialize で未設定値とそれ以外を区別する方法
記事No11534
投稿日: 2015/11/26(Thu) 19:55
投稿者たかし

Nullable を使用して解決できました。
Nullable の存在を知りませんでした。
ありがとうございました。

---------------------------------

Public Class Person
  Public Name As String
  Public Year As Nullable(Of Integer)
End Class

とすることで
よーこの Year は Nothing となり
たろうの Year は 0 となりました。

処理で使用する際は

If .Year IsNot Nothing Then
   MsgBox "Year = " & .Year
End If

という感じです。

Serialize で xml 出力すると
<Year xsi:nil="true" />
となってしまい、違和感がありますが、
xml に出力することはない( xml を読み込むだけ)ので
問題ありません。

ちなみに、最悪、次のような方法を考えていました。

Public Class Person
  Public Name As String
  Public Year As Integer = Integer.MinValue
End Class

If .Year <> Integer.MinValue Then
   MsgBox "Year = " & .Year
End If

ただ、年齢とかであれば、絶対ありえない値というものがある(負の値など)ので
この方法でなんとか可能ですが、
中には、絶対ありえない値、というものがないものもあるので…

[ツリー表示へ]
タイトルRe^3: Deserialize で未設定値とそれ以外を区別する方法
記事No11535
投稿日: 2015/11/26(Thu) 20:17
投稿者魔界の仮面弁士
>   Public Year As Nullable(Of Integer)

ちなみに、2008 以降では「As Integer?」とも書けます。

Dim a As Integer? = 1
Dim b As Integer? = Nothing
Dim c As Integer? = 2

Dim x As Integer? = a + c    ' 3
Dim y As Integer? = b + c    ' Nothing

[ツリー表示へ]