OITA: Oika's Information Technological Activities

@oika 情報技術的活動日誌。

C# DataSet/DataTableの値をキャストするかParseするか

以前、DataRowとNullの微妙な関係というのを書いたけど、
相変わらず、型なしDataSetの値の扱いは気難しいという話。

まずは、int型のカラムを一つだけ持つDataTableを用意して、
それ用の新規DataRowを作って、適当な値を入れる。

var dt = new DataTable();  
dt.Columns.Add("FldInt", typeof(int));  
  
var row = dt.NewRow();  
row["FldInt"] = 1234;  

こうすると、中に入ってるのはint値なので、
以下のようにして取り出せる。ここまでは良い。

var val = (int)row["FldInt"];  

だけど、これを以下のようにshortやlongにキャストしようとすると
失敗するのである。

//throws InvalidCastException  
var sVal = (short)row["FldInt"];  
  
//throws InvalidCastException  
var lVal = (long)row["FldInt"];  

もちろん、一度intにキャストして取得した値から
shortやlongにキャストするのは何の問題もない。

結局、IEnumerable.Castメソッドでint→longはできないという話と同じで、
DataRowに入る時点でボックス化されていて、ボックス化解除変換になるから
失敗するんだな。

DataAdapterでDBからDataTableにがばっと値をとってきたときに
もとのカラム型がINTEGERだろうがSMALLINTだろうが
とりあえずintにしてしまえっていう横着なことを自分はよくやるので、
上記のようにキャストでとるのはちょっとこわくて、
以下のように文字列にしてからParseしておくことも多い。
パフォーマンスはいくらか悪いんだろうけど…。

var val = int.Parse(row["FldInt"].ToString());