Delphi Prism:如何重写 GetHashCode 和 Equals 方法以使 IndexOf 正常工作?

发布于 2024-12-04 23:53:30 字数 1624 浏览 0 评论 0原文

我不确定我这样做是否正确。我在列表框中有一个对象列表,需要使用 IndexOf 来获取列表中对象的索引。

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

alrm 是 TAlarm 类的对象。

基于 StackOverflow C# 问题 (如何我可以获取列表框中项目的索引吗?),我尝试重写 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 并且这些重写方法永远不会被调用或触发。

我是否正确实施了这些覆盖?如果没有,我应该如何覆盖它们?

示例代码或提示或线索将不胜感激。谢谢,

更新:对于 David Heffernan 和其他发表评论或回答的人,我认为问题可能是我传递了两个不同的对象,正如 Rob 的最后评论所述。我确实使用 TAlarmGroup 填充列表框 (UI),但将 TAlarm 传递到 IndexOf,尽管它们都是相同的类。这可能是我的问题。我真正想做的是用 TAlarmGroup 对象填充列表框,并通过传入字符串(标记名)通过 listbox.indexof 搜索对象位置。 Delphi XE 上就是这样做的,效果很好。上面的代码不是实际的代码。一旦我清除了代码中的混乱,它可能会在不重写 GetHashcode 和 Equals 方法的情况下工作。

更新:我想,我在这里偶然发现了一些东西。在Delphi XE或以下版本中,ListBox(UI)提供了一个名为AddObject的方法。它的参数分别是一个字符串和一个对象。因此,当我将对象填充到列表框中时,我还提供了与之一起使用的字符串。当我搜索时,我传递了一个字符串或警报组名称。 IndexOf 在此字符串上针对我提供的每个对象的字符串进行搜索,而不是针对对象的字段 (TagName)。在Delphi Prism中,列表框没有与AddObject方法类似的方法,而只有仅接受对象作为参数的Add。

I am not sure if I am doing this right. I have a list of objects in the listbox and need to use IndexOf to get an object's index in the list.

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

alrm is an object of TAlarm class.

Based on a StackOverflow C# question (How Can I Get the Index of An Item in a ListBox?), I try to override GetHashCode and Equals method, but still it doesn't work right.

Overriden Method:

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;

This is how I populate AlarmListBox:

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

Compiler compiles without any errors, but when I debug the program line by line it always returns -1 and these overridden methods are never called or fired.

Am I implementing these overrides correctly? If not, how should I override them?

Sample code or hints or clues will be appreciated. Thanks,

UPDATE: To David Heffernan and others who have commented or answered, I think the problem might be that I am passing in two different object as Rob's last comment states. I do populate Listbox (UI) with TAlarmGroup but pass in TAlarm into IndexOf, although they both are identical classes. This is probably my problem. What I am really trying to do is populate Listbox with TAlarmGroup objects and through listbox.indexof by passing in the string (Tagname) I search for the object location. That's how it is done on Delphi XE it works great. The code above is not the actual code. Once I clean up the confusion in my code, it will probably work without overriding the GetHashcode and Equals method.

UPDATE: I think, I have stumbled onto something here. On Delphi XE or below, ListBox (UI) provides a method called AddObject. It's parameters are a string and an object respectively. So, when I populated objects into listbox I also provided the string to go along with it. When I searched I passed in a string or the alarm group name. IndexOf searched on this string against the string it had for each object I provided and not against the object's field (TagName). In Delphi Prism, listbox doesn't have a similar method as AddObject method but only Add that only accepts object as a parameter.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

腻橙味 2024-12-11 23:53:30

下面是使用您提供的基本 TAlarm 类执行您想要的操作的示例。我还提供了似乎有效的重载 EqualsGetHashCode 实现。 (再次强调,我不是 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;

以下是单击 Button 后在 ComboBox 中选择的项目的外观>:

ListBox 中找到的对象的屏幕截图

Here's an example of doing what you want with the base TAlarm class you provided. I've also provided implementations of the overloaded Equals and GetHashCode that seem to work. (Again, I'm not a Prism/.NET developer; just trying to help out here.)

// 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;

Here's how it looks with an item selected in the ComboBox after clicking the Button:

Screen capture of object found in ListBox

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文