2009-09-21 2 views
4

Пусть у меня есть класспроблема C# Queue

XYNode 
{ 
    protected int mX; 
    protected int mY; 
} 

и очередь

Queue<XyNode> testQueue = new Queue<XYNode>(); 

Я хочу, чтобы проверить, является ли узел с этой конкретной х и у координаты уже в очереди. Следующая явно не работает:

testQueue.Contains(new XYNode(testX, testY)) 

, потому что даже если узел с этими координатами находится в очереди, мы тестируем против другого объекта XYNode поэтому он всегда будет возвращать ложь.

Какое правильное решение?

ответ

17

Самый простой способ - переопределить Equals так, чтобы один XYNode знал, равен ли он другому XYNode. Вы должны переопределить GetHashCode() в то же время и, возможно, также реализовать IEquatable<XYNode>, чтобы обеспечить строго типизированное сравнение равенства.

В качестве альтернативы, вы можете написать IEqualityComparer<XYNode> реализации сравнить любые два узла и возвращает ли не ты, они же - и затем передать, что в обращение к appropriate overload of the Contains extension method, определенным в Enumerable (при условии, что вы используете .NET 3.5).

Другие вещи, чтобы рассмотреть следующие вопросы:

  • Не могли бы вы использовать частные поля вместо защищенных из них?
  • Может ли ваш класс быть запечатан?
  • Может ли ваш класс быть неизменным?
  • Должен ли ваш класс быть структурой вместо этого? (Судебный вызов ...)
  • Должны ли вы перегружать операторы == и! =?
+1

довольно скоро вы собираетесь выиграть stackoverflow.com – scottm

+0

+1 Для частичного ответа с улучшением призрака. – ChaosPandion

+0

"ПЕРВЫЙ"? призрак? –

5

Для иллюстрации Джона Скита ... оригинальный ... ответ:

class XYNode { 
    protected int mX; 
    protected int mY; 

    public override bool Equals(Object obj) { 
     if (obj == null || this.GetType() != obj.GetType()) { return false; } 

     XYNode otherNode = (XYNode)obj; 
     return (this.mX == other.mX) && (this.mY == other.mY); 
    } 
} 

Это является довольно упрощенным решением. Есть много дополнительных факторов, на которые Джон уже упомянул.

+0

Вам нужно указать переопределение, а параметр должен быть объектом. – ChaosPandion

+0

@ChaosPandion: Спасибо. –

+0

Одна из удобных задач создания класса - это то, что вы можете просто использовать как/вместо вызова 'GetType()' - вам не нужно беспокоиться о том, чтобы получить экземпляр подкласса. –

0

С помощью .NET Framework 3.5 вы можете использовать метод расширения LINQ и .Any() для IEnumerable<T>, чтобы упростить сравнение. Первый импорт, что пространство имен (импортируется по умолчанию при создании нового файла класса):

using System.Linq; 

Этот метод возвращает bool так же, как .Contains():

bool exists = testQueue.Any(node => node.X == testX && node.Y == testY); 

Однако для этой работы вам необходимо будет сделать mX и mY общедоступным.Вы можете сохранить protected аспект установки значений этих переменных следующим образом:

class XYNode 
{ 
    public int X { get; protected set; } 
    public int Y { get; protected set; } 
} 
0

Вы можете просто перебирать с foreach и проверить X и Y из ваших XYNode на каждом элементе.