列表IndexOf返回-1,即使有匹配的对象c#。

4

我有以下代码来查找 List<ColorItem>ColorItem 对象的索引:

//Get the index of the color item
var colorList = dialogViewModel.Items;
var colorItem = new ColorItem();
colorItem = sp.TileColorItem;
int index = colorList.IndexOf(colorItem);

尽管列表中有匹配的对象,但index始终返回-1。我错过了什么吗?

colorList content

colorItem content


有两个值相同的colorItems,但它们是不同的对象。一个列表中,另一个则不在 - Corak
ColorItem 是你自己的类吗?如果是,你可以通过重写 Equals 方法来使其工作...但我们需要上下文。 - Jon Skeet
2个回答

8
List<T>.IndexOf方法会查找在列表中与你传入的值相等的项。对于类,默认情况下,等同性仅为对象标识 - 因此,无论其字段如何,两个不同的对象都被视为不等。但是,您可以通过重写Equals方法来更改这一点。
如果ColorItem是您自己的类,则可以通过适当地重写Equals(和GetHashCode;它不被List<T>.IndexOf使用,但应始终被覆盖以与Equals保持一致)使其正常工作。
public sealed class ColorItem : IEquatable<ColorItem>
{
    private readonly string text;
    private readonly Color color;

    public string Text { get { return text; } }
    public Color Color { get { return color; } }

    public ColorItem(string text, Color color)
    {
        this.text = text;
        this.color = color;
    }

    public override bool Equals(object other)
    {
        return Equals(other as ColorItem);
    }

    public bool Equals(ColorItem otherItem)
    {
        if (otherItem == null)
        {
            return false;
        }
        return otherItem.Text == text && otherItem.Color == color;
    }

    public override int GetHashCode()
    {
        int hash = 19;
        hash = hash * 31 + (text == null ? 0 : text.GetHashCode());
        hash = hash * 31 + color.GetHashCode();
        return hash;
    }
}

现在,IndexOf 应该可以正常工作了。
(我实现了 IEquatable<ColorItem>,这是一个通用的好习惯。虽然在这里并不是必需的。)

1
你正在将colorItem分配给sp.TileColorItem,但它不在colorList中。这就是为什么如果你调用colorList.IndexOf(colorItem),它会返回-1的原因。 你可能想使用类似这样的代码:
int index;
foreach (var item in colorList)
{
    if (item.Text == sp.TileColorItem)
    {
        index = colorList.IndexOf(item);
    }
}

1
不行。最简单的方法可能是通过循环计数器遍历列表,并在颜色值相等时返回。 - Corak
2
不,我认为这不是最好的方法。如果它们被看作值来处理,其中不同的对象可以视为相等,则重写 Equals 以使 IndexOf 工作是有意义的。在那时,您也可以将其用作字典键等。如果相关的类不在我的控制下,我只会手动循环像这样的代码。 - Jon Skeet
@JonSkeet 你可能是对的,但我认为对于初学者来说,循环List以查找值要比进行一些棘手的操作(如重写)容易得多。如果项目很小,则无需覆盖ColorItem类的Equals方法(该类可以是第三方框架的一部分)。 - Andrey Gordeev
1
@AndreyGordeev:而我认为值得解释发生了什么,并至少给出选项。否则,原帖的作者将相信他们无法做他们想做的事情,并且当IndexOf适用于其他类时,可能会很容易地感到困惑。 即使您将要循环,我也不会使用 IndexOf 再次循环,而是使用计数器。 - Jon Skeet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接