気になった事を自由に書いてます。
      
更新:2011/03/31
DataTableを比較してみた。
C#はEquals()というオブジェクトの等価を行うメソッドが用意されている。
これを使えばDataTableの比較結果なんて簡単だ、と思い試してみるとダメでした。

テストコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
DataRow dr = null;

// 列を定義
dt1.Columns.Add("A", Type.GetType("System.String"));
dt1.Columns.Add("B", Type.GetType("System.String"));
dt1.Columns.Add("C", Type.GetType("System.String"));

dt2.Columns.Add("A", Type.GetType("System.String"));
dt2.Columns.Add("B", Type.GetType("System.String"));
dt2.Columns.Add("C", Type.GetType("System.String"));

// dt1 データを格納
for (int i = 1; i <= 5; i++)
{
    dr = dt1.NewRow();
    dr["A"] = "A_" + i.ToString("00");
    dr["B"] = "B_" + i.ToString("00");
    dr["C"] = "C_" + i.ToString("00");
    dt1.Rows.Add(dr);
}

// dt2 データを格納
for (int i = 1; i <= 5; i++)
{
    dr = dt2.NewRow();
    dr["A"] = "A_" + i.ToString("00");
    dr["B"] = "B_" + i.ToString("00");
    dr["C"] = "C_" + i.ToString("00");
    dt2.Rows.Add(dr);
}

if (dt1.Equals(dt2))
{
    Console.WriteLine("dt1とdt2は同じです。");
}
else
{
    Console.WriteLine("dt1とdt2は異なります。");
}

出力
dt1とdt2は異なります。

とても残念な結果です。
調べていくとEquals()は2通りの等価があるようです。
1つは値の等価で2つのオブジェクトの値が同じかどうかを意味します。
2つめは参照の等価となります。参照の等価とはオブジェクトがまったく同じ参照先
を見ているかどうかを意味します。
このどちらの等価にあたるかはクラスが「値型」か「参照型」かで決定します。
このサンプルで比較しているDataTableは「参照型」なので、2つめの等価となり
とても残念な結果が生まれたわけです。

こうすると同じものと判断されます。

テストコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DataTable dt1 = new DataTable();
DataRow dr = null;

// 列を定義
dt1.Columns.Add("A", Type.GetType("System.String"));
dt1.Columns.Add("B", Type.GetType("System.String"));
dt1.Columns.Add("C", Type.GetType("System.String"));

DataTable dt2 = dt1;
if (dt1.Equals(dt2))
{
    Console.WriteLine("dt1とdt2は同じです。");
}
else
{
    Console.WriteLine("dt1とdt2は異なります。");
}

出力
dt1とdt2は同じです。

dt2はdt1で作成したメモリ領域を参照してるので当然ながら同じになります。
しかし同じになるのは当たり前で、まったくもって私が期待してたものと異なります。
なので比較を行うメソッドを作ってみました。

テストコード
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public bool DataTableCompare(DataTable dt1, DataTable dt2)
{
    if (dt1 == null && dt2 != null) { return false; }
    if (dt1 != null && dt2 == null) { return false; }
    if (dt1 == null && dt2 == null) { return true; }
    if (dt1.Rows.Count != dt2.Rows.Count) { return false; }

    for (int rowIndex = 0; rowIndex < dt2.Rows.Count; rowIndex++)
    {
        for (int colIndex = 0; colIndex < dt2.Columns.Count; colIndex++)
        {
            if(!dt1.Rows[rowIndex][colIndex].Equals(
                dt2.Rows[rowIndex][colIndex]))
            {
                return false;
            }
        }
    }
    return true;
}

このメソッドを使うときの前提条件として Rows[rowIndex, colIndex]に入る型は
int、char等の値型とします。string型は参照型ですが参照ではなく値の比較を
行うよう定義されてるのでOKです。
Rows[rowIndex, colIndex]はObject型でなので中身が値型ならEquals()を使っても
期待した値が返ってくるという考えです。

      



Effective C# 4.0
ビル・ワグナー
¥ 3,780



Copyright (C) 2011 - 2017 猫の気ままなC#日記