是否存在任何类似集合的集合(如HashSet<T>
),它们在身份而不是哈希码/等式上运行?如果我只想要一个1000(或更多)对象,我不关心是否被认为是平等的,但需要检查我之前是否已经收到过该对象?
[编辑]
特别地,在这种情况下,我交给GameObject
(来自游戏引擎,我无法控制,我无法更改代码)存储在一个集合中。现在一般来说,使用哈希码和相等可能很好,它只是打击了我(至少在这种特殊情况下)我不需要它。我只需要确保一个对象不会重新添加到集合中。我不知道在我正在处理的类中是否覆盖了GetHashCode
或等式。
[编辑2]
所以,试图用身份来描述我的意思。如果您在C#中创建了两个Object
(使用new Object()
),则有两种方法可以检查它们是否“相等”。一种是检查是否相等(使用Object.Equals
或==
),另一种是检查它们是否是相同的对象(引用相等)。如果我没记错,在VB中,您可以使用obj1 Is obj2
执行此操作。这是通过身份检查,而不是通过相等。换句话说,我正在寻找一个适用于引用相等的集合,而不是可覆盖的类型。
答案 0 :(得分:0)
你可以创建一个实现IList接口的类,在这个类中你将拥有一个List,它将保存对象,你将通过列表几乎所有方法,除了:添加,包含 插入和设置[索引] ,您将使用方法ReferenceEquals
检查两个对象是否具有相同的引用。
如果你有这门课程
public class Person
{
protected bool Equals(Person other) => Id == other?.Id;
public override int GetHashCode() => Id;
public static bool operator ==(Person left, Person right) => Equals(left, right);
public static bool operator !=(Person left, Person right) => !Equals(left, right);
public int Id { get; set; }
public override bool Equals(object obj) => Equals(obj as Person);
}
然后,如果您运行此代码
var person = new Person() { Id = 1 };
var person2 = new Person() { Id = 1 };
Console.WriteLine(person == person2);
你会得到两个人都是平等的。
现在让我们创建一个ListByReference<T>
public class ListByReference<T> : IList<T>
{
private readonly List<T> _list;
public ListByReference()
{
_list = new List<T>();
}
public IEnumerator<T> GetEnumerator() => _list.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public void Add(T item)
{
if (ObjectExists(item))
return;
_list.Add(item);
}
public void Clear() => _list.Clear();
public bool Contains(T item) => ObjectExists(item);
public void CopyTo(T[] array, int arrayIndex) => _list.CopyTo(array, arrayIndex);
public bool Remove(T item) => _list.Remove(item);
public int Count => _list.Count;
public bool IsReadOnly => false;
public int IndexOf(T item) => _list.IndexOf(item);
public void Insert(int index, T item)
{
if (ObjectExists(item))
return;
_list.Insert(index, item);
}
public void RemoveAt(int index) => _list.RemoveAt(index);
public T this[int index]
{
get { return _list[index]; }
set
{
if (ObjectExists(value))
return;
_list[index] = value;
}
}
private bool ObjectExists(T item) => _list.Any(i => ReferenceEquals(i, item));
}
然后我们可以测试我们的课程
var person = new Person() { Id = 1 };
var person2 = new Person() { Id = 1 };
var listByReference = new ListByReference<Person>();
listByReference.Add(person);
listByReference.Add(person2);
listByReference.Add(person);
Console.WriteLine(listByReference.Count);
Console.WriteLine(listByReference.Contains(person));
Console.WriteLine(listByReference.Contains(person2));
Console.WriteLine(listByReference.Contains(new Person() { Id = 1 }));
输出
2
真
真
假
正如你所看到的那样,我调用了3次添加,但我列表中只有2个人,因为第一个已添加。
当我尝试添加一些已经存在的对象时,我选择不抛出异常,但如果你愿意,可以修改。