2016-04-01 32 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; 
    } 
} 

我的程序,其中在調試時我可以看到兩次相同的位置。

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值運行函數兩次,那麼有兩個鍵的位置與x,y值相似。

我應該如何更新位置而不是插入新位置。

+1

是否定位了一個結構,並且重寫了Equals和GetHashCode語義?這可能是問題 – Casey

+2

如果Position只是一個對象,它將以引用相等方式進行操作,並且它不會像您期望的那樣工作,除非您擁有與密鑰完全相同的對象 – Casey

+0

使位置成爲結構而不是類。 – Camo

回答

2

如果Position是一個類,那麼通過比較它們的引用來比較兩個不同的Position實例。例如,即使它們包含相同的值,它們也被認爲是不同的。

您可以通過實現IEqualityComparer<Position>解決這個問題,並傳遞到字典:

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

或者你可以覆蓋位置級別EqualsGetHashCode

假設Position平等是由具有限定等於XY你:

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類型只包含兩個整數,它是一個很好的候選者,可以作爲一個值類型實現(struct)。只需將class Position更改爲struct Position即可解決您的問題,因爲值類型的默認Equals是通過比較所有字段(例如XY)來實現的。但是,如果你決定去struct路線,我仍然建議你重寫Equals和相關的方法,以避免反映的成本以及特別是在比較浮點值時可能發生的其他警告。值類型旨在用作優化,如果您不需要這種優化,則通過堅持引用類型可以避免更少的細微錯誤。

請注意,由於您使用Position作爲關鍵,因此Position類型是不可變的。

+0

如果你打算覆蓋Equals,我認爲你應該重寫'=='操作符,否則這種行爲可能會令人驚訝。 – Casey