9

おそらく本当に簡単なことですが、私はそれを見ることができません...

LINQ で MS Access クエリを複製しています。私は C# の方が好きなので、最初に C# で書いてテストし、次にそれを VB.Net 構文に変換しました。私が知る限り、2 つのクエリは同一である必要がありますが、C# クエリは正しい結果を返しますが、VB.NET クエリはゼロの結果を返します。

違いがどこにあるのか誰にもわかりますか?

C# クエリ:

var table1 = dc.MainTable.Where(o => o.Year == 423).ToList().Select(o => new
{
    Key_ID = o.Key_ID.Value,
    CropID = o.CropID.Value,
    GroupID = o.GroupID.Value,
    Surface1 = o.Surface1.Value,
    Surface2 = o.Surface2.Value
});

var table2 = dc.OtherTable.Where(o => o.Year == 423).ToList().Select(o => new
{
    Key_ID = o.Key_ID.Value,
    CropID = int.Parse(o.SAKU_CD),
    GroupID = int.Parse(o.SAN_DAN_NO),
    Surface1 = Convert.ToDouble(o.KEIHAN_MEN.Value),
    Surface2 = Convert.ToDouble(o.SAKU_MEN.Value)
});

var output = table1.Join(table2, t1 => new 
{ 
    t1.Key_ID, 
    t1.CropID, 
    t1.GroupID, 
    t1.Surface1, 
    t1.Surface2 
}, 
t2 => new 
{ 
    t2.Key_ID, 
    t2.CropID, 
    t2.GroupID, 
    t2.Surface1, 
    t2.Surface2 
}, (t1, t2) => new OutputDataType() 
{ 
    Key_ID = t1.Key_ID, 
    Year = 423 
}).ToList();

VB.NET クエリ:

Dim table1 = MainTable.Where(Function(o) o.Year.Value = 423).ToList().Select(Function(o) New With
{
    .Key_ID = o.Key_ID.Value,
    .CropID = o.CropID.Value,
    .GroupID = o.GroupID.Value,
    .Surface1 = o.Surface1.Value,
    .Surface2 = o.Surface2.Value
}).ToList()

Dim table2 = OtherTable.Where(Function(o) o.Year.Value = 423).ToList().Select(Function(o) New With
{
    .Key_ID = o.Key_ID.Value,
    .CropID = Convert.ToInt32(o.SAKU_CD),
    .GroupID = Convert.ToInt32(o.SAN_DAN_NO),
    .Surface1 = Convert.ToDouble(o.KEIHAN_MEN.Value),
    .Surface2 = Convert.ToDouble(o.SAKU_MEN.Value)
}).ToList()

Dim output = table1.Join(table2, Function(t1) New With
{
    t1.Key_ID,
    t1.CropID,
    t1.GroupID,
    t1.Surface1,
    t1.Surface2
}, Function(t2) New With
{
    t2.Key_ID,
    t2.CropID,
    t2.GroupID,
    t2.Surface1,
    t2.Surface2
}, Function(t1, t2) New OutputDataType With {.Key_ID = t1.Key_ID, .Year = 423}).ToList()

C# と VB.Net の両方table1で とtable2は同じであるため、失敗するのは である必要がJoinあります。

編集

Join次のように、VB.Net をクエリ構文に変更しました。

Dim output = From t1 In MainTable
                 Join t2 In OtherTable
                 On t1.Key_ID Equals t2.Key_ID And t1.GroupID Equals t2.GroupID And t1.CropID Equals t2.CropID And t1.Surface1 Equals t2.Surface1 And t1.Surface2 Equals t2.Surface2
                 Select New OutputDataTypeData With {.Key_ID = t1.Key_ID, .Year = 423}

正しい結果が得られます。Joinしかし、これが拡張メソッドの構文とどのように違うのか本当にわかりませんか?

4

1 に答える 1

12

Join拡張メソッドを使用すると、outerKeySelectorおよびinnerKeySelector引数として指定したキーがメソッドを使用して比較されEqualsます。

ただし、C# と VB.Net では、匿名型の処理が次のように異なります。

C#

var a = new {Foo = 1, Bar = 2 };
var b = new {Foo = 1, Bar = 2 };
bool result = a.Equals(b); // true

VB.Net

Dim a = new with {.Foo = 1, .Bar = 2}
Dim b = new with {.Foo = 1, .Bar = 2}
Dim result = a.Equals(b) ' False '

ここで何が起こっているのですか?

C# は値の等価性を使用して 2 つのオブジェクトを比較し、プロパティの値を比較します。

VB.Net は参照の等価性を使用して 2 つのオブジェクトを比較するため、結果は になりFalseます。

Keyコードを機能させるには、次のキーワードを使用してプロパティを比較するように VB.Net に明示的に指示する必要があります。

キー プロパティは、いくつかの基本的な点で非キー プロパティとは異なります。

  • 2 つのインスタンスが等しいかどうかを判断するために、キー プロパティの値のみが比較されます。
  • キー プロパティの値は読み取り専用で、変更できません。
  • コンパイラが生成する匿名型のハッシュ コード アルゴリズムには、主要なプロパティ値のみが含まれます。
Dim a = new with {Key .Foo = 1, Key .Bar = 2}
Dim b = new with {Key .Foo = 1, Key .Bar = 2}
Dim result = a.Equals(b) # True

この場合、匿名の型/オブジェクトを比較するのではなく、単にints とdoubles を比較しているため、クエリ構文は機能します。

于 2013-02-18T08:12:40.870 に答える