Delphi Prism: как переопределить методы GetHashCode и Equals для правильной работы IndexOf? - PullRequest
1 голос
/ 16 сентября 2011

Я не уверен, правильно ли я это делаю. У меня есть список объектов в списке, и мне нужно использовать IndexOf, чтобы получить индекс объекта в списке.

if AlarmListBox.items.indexOf(alrm.Tagname) = -1 then

alrm является объектом класса TAlarm.

Основываясь на вопросе StackOverflow C # ( Как я могу получить индекс элемента в ListBox? ), я пытаюсь переопределить метод GetHashCode и метод Equals, но все равно он работает неправильно.

Переопределенный метод:

TAlarm = class(System.Object)
  TagName:string;
  private
  protected
  public
  method Equals(obj:System.Object):Boolean; override;
  method GetHashCode:Int32; Override;
end;

method TAlarm.Equals(obj: system.Object):Boolean;
begin
    result := TAlarm(obj).Tagname.Equals(self.Tagname);
end;

method TAlarm.GetHashCode:Int32;
begin
    result := self.GetHashCode;
end;

Вот как я заполняю AlarmListBox:

AlmGrp:= new TAlarmGroup;
AlarmListBox.items.Add(AlmGrp);

Компилятор компилируется без ошибок, но когда я построчно отлаживаю программу, она всегда возвращает -1, и эти переопределенные методы никогда не вызываются и не запускаются.

Правильно ли я выполняю эти переопределения? Если нет, то как мне их переопределить?

Пример кода или подсказки или подсказки будут оценены. Спасибо,

ОБНОВЛЕНИЕ: Для Дэвида Хеффернана и других, кто прокомментировал или ответил, я думаю, что проблема может быть в том, что я передаю два разных объекта, как говорится в последнем комментарии Роба. Я заполняю Listbox (UI) TAlarmGroup, но передаю TAlarm в IndexOf, хотя они оба являются идентичными классами. Это наверное моя проблема. Что я действительно пытаюсь сделать, так это заполнить Listbox объектами TAlarmGroup и через listbox.indexof, передав строку (Tagname), в которой я ищу местоположение объекта. Вот как это делается на Delphi XE, он прекрасно работает. Код выше не фактический код. После устранения путаницы в моем коде он, вероятно, будет работать без переопределения методов GetHashcode и Equals.

ОБНОВЛЕНИЕ: Я думаю, я наткнулся здесь на что-то. В Delphi XE или ниже ListBox (UI) предоставляет метод с именем AddObject. Это параметры строки и объекта соответственно. Таким образом, когда я заполнял объекты в списке, я также предоставлял строку для этого. Когда я искал, я передал строку или имя группы сигналов тревоги. IndexOf выполнял поиск в этой строке по строке, которую он имел для каждого предоставленного мной объекта, а не по полю объекта (TagName). В Delphi Prism список не имеет метода, аналогичного методу AddObject, а только Add, который принимает объект только в качестве параметра.

1 Ответ

2 голосов
/ 16 сентября 2011

Вот пример того, что вы хотите делать с базовым классом TAlarm, который вы указали. Я также предоставил реализации перегруженных Equals и GetHashCode, которые, кажется, работают. (Опять же, я не разработчик Prism / .NET; просто пытаюсь помочь здесь.)

// In AlarmClass.pas
type
  TAlarm = class(System.Object)
    TagName:string;
  private
  protected
  public
    constructor;
    method Equals(obj:System.Object): Boolean; override;
    method GetHashCode:Int32; Override;
    method ToString(): String; override;
end;

implementation

method TAlarm.GetHashCode: Int32;
begin
  if Self = nil then
    Result := inherited 
  else
    Result := Self.TagName.GetHashCode;
end;

constructor TAlarm;
begin
  inherited;
end;

method TAlarm.Equals(obj: System.Object): Boolean;
begin
  if  (obj = nil) or (GetType() <> obj.GetType()) then
    Exit(False);
  Result := TAlarm(obj).TagName.Equals(Self.TagName);
end;

method TAlarm.ToString(): String;
begin
  Result := Self.TagName;
end;

// In MainForm.pas
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
  Idx: Integer;
begin
  Idx := ComboBox1.SelectedIndex;
  if Idx <> -1 then
    ListBox1.SelectedIndex := ListBox1.Items.IndexOf(ComboBox1.Items[Idx]);
end;

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
var
  i, j: Integer;
  Alarm: TAlarm;
  aList: Array[0..4] of Object;
  aFind: Array[0..1] of Object;
begin
  j := 0;
  for i := 0 to 4 do
  begin
    Alarm := new TAlarm;
    Alarm.TagName := String.Format('Alarm{0}', i);
    aList[i] := Alarm;
    // Place items 1 & 3 in another array of searchable items -
    // just for fun. Not suggesting implementing your app this way
    // by any means.
    if (i mod 2) > 0 then
    begin
      aFind[j] := Alarm;
      Inc(j);
    end;
  end;
  ListBox1.Items.AddRange(aList);
  ComboBox1.Items.AddRange(aFind);
end;

Вот как это выглядит с элементом, выбранным в ComboBox после нажатия Button:

Screen capture of object found in ListBox

...