2016-04-01 13 views
0

イムマップ値更新しよう:C#辞書の更新が同じインデックスに挿入し

マイMatrixクラス(マップ付き)

class Matrix 
{ 
    // m = column 
    // n = row 
    int m, n; 
    Dictionary<Position, double> values; 

    public Matrix(int M, int N) 
    { 
     this.m = M; 
     this.n = N; 
     values = new Dictionary<Position, double>(); 
     // Zorgen dat de matrix vol zit met waardes door alles op 0 te zetten 
     for(int i = 0; i < m; i ++) 
     { 
      for (int j = 0; j < n; j++) 
      { 
       values.Add(new Position(i,j), 0); 
      } 
     } 
    } 

    public void setValue(int x, int y, int value) 
    { 
     values[new Position(x, y)] = value; 
     // 
    } 

} 

マイポジションクラス

class Position 
{ 

    int x, y; 

    public Position(int x, int y) 
    { 
     this.x = x; 
     this.y = y; 
    } 
} 

マイプログラム私はデバッグ中に同じ位置を2回見ることができます。

static void Main(string[] args) 
    { 
     Matrix m1 = new Matrix(2,3); 
     m1.setValue(1, 1, 1); 
     m1.setValue(3, 4, 1); 

     Console.ReadLine(); 
    } 

位置は、xとyの値を持つクラスです。私がしたいことは、特定のx、y値を持つ位置の値を与えられた値に更新することです。

しかし、同じx、y値で2回関数を実行すると、位置がsimilair x、y値の2つのキーがあります。

新しい位置を挿入する代わりに位置を更新する必要があります。

+1

位置は構造体で、EqualsとGetHashCodeのセマンティクスをオーバーライドしましたか?それはおそらく問題です – Casey

+2

Positionが単にオブジェクトであれば、それは参照平等で動作し、キーとして使用するのと全く同じオブジェクトを持たない限り期待通りに動作しません。 – Casey

+0

位置をクラスではなく構造にします。 – Camo

答えて

2

Positionがクラスの場合、2つの異なるPositionインスタンスが、それらの参照を比較することによって比較されます。たとえば、同じ値が含まれていても異なると見なされます。

あなたはIEqualityComparer<Position>を実装することにより、この問題を解決し、辞書にそれを渡すことができます。

var dictionary = new new Dictionary<Position, double>(new PositionEqualityComparer()); 

それとも、位置クラスでEqualsGetHashCodeを上書きすることができます。

Positionの平等は、あなたが得るY等しいXを有することにより、定義されていることと仮定:

class PositionEqualityComparer : IEqualityComparer<Position> { 

    public Boolean Equals(Position position1, Position position2) { 
    return position1.X == position2.X && position1.Y == position2.Y; 
    } 

    public Int32 GetHashCode(Position position) { 
    unchecked { 
     const Int32 Multiplier = -1521134295; 
     var hash = -5273937; 
     hash = hash*Multiplier + position.X.GetHashCode(); 
     hash = hash*Multiplier + position.Y.GetHashCode(); 
     return hash; 
    } 
    } 

} 

それとも、Positionクラスに直接平等の同じ種類を実装する場合を:

class Position : IEquatable<Position> { 

    public Boolean Equals(Position other) { 
    return X == other.X && Y == other.Y; 
    } 

    public override Boolean Equals(Object obj) { 
    var position = obj as Position; 
    return position != null ? Equals(position) : false; 
    } 

    public override Int32 GetHashCode() { 
    unchecked { 
     const Int32 Multiplier = -1521134295; 
     var hash = -5273937; 
     hash = hash*Multiplier + X.GetHashCode(); 
     hash = hash*Multiplier + Y.GetHashCode(); 
     return hash; 
    } 
    } 

} 

場合Positionタイプには2つの整数しか含まれていませんが、値タイプ(struct)として実装することをお勧めします。すべてのフィールド(例:XおよびY)を比較することによって、値タイプのデフォルトEqualsが実装されているため、class Positionstruct Positionに変更するだけで問題は解決します。

structルートを使用する場合は、Equalsと関連するメソッドをオーバーライドして、特に浮動小数点値の比較時に発生する可能性のある反映やその他の警告を回避することをお勧めします。値の型は最適化を目的としており、最適化が不要な場合は、参照型を使用して微妙なエラーを減らすことができます。

Positionをキーとして使用しているので、Positionタイプは不変であることが重要です。

+0

Equalsをオーバーライドする場合は、 '=='演算子をオーバーライドする必要があると思います。そうしないと、動作が驚くかもしれません。 – Casey

関連する問題