Я пытаюсь написать запрос Linq, который возвращает массив объектов с уникальными значениями в их конструкторах. Для целочисленных типов Distinct возвращает только одну копию каждого значения, но когда я пытаюсь создать свой список объектов, все разваливается. Я подозреваю, что это проблема с оператором равенства для моего класса, но когда я устанавливаю точку останова, она никогда не попадает.
Фильтрация повторяющегося int в подвыражении решает проблему, а также избавляет меня от создания объектов, которые будут следует немедленно отбросить, но мне любопытно, почему эта версия не работает.
ОБНОВЛЕНИЕ: 23:04 Некоторые люди указали, что MyType не отменяет GetHashCode (). Боюсь, я слишком упростил пример. Исходный MyType действительно его реализует. Я добавил его ниже, измененный только для того, чтобы поместить хеш-код во временную переменную перед его возвратом.
Пройдя через отладчик, я вижу, что все пять вызовов GetHashCode возвращают другое значение. А поскольку MyType наследуется только от Object, предположительно, это то же поведение, что и Object.
Правильно ли я заключу, что вместо этого хеш должен основываться на содержимом Value? Это была моя первая попытка переопределить операторы, и в то время не казалось, что GetHashCode требует особой изысканности. (Впервые одна из моих проверок на равенство не сработала должным образом.)
class Program
{
static void Main(string[] args)
{
int[] list = { 1, 3, 4, 4, 5 };
int[] list2 =
(from value in list
select value).Distinct().ToArray(); // One copy of each value.
MyType[] distinct =
(from value in list
select new MyType(value)).Distinct().ToArray(); // Two objects created with 4.
Array.ForEach(distinct, value => Console.WriteLine(value));
}
}
class MyType
{
public int Value { get; private set; }
public MyType(int arg)
{
Value = arg;
}
public override int GetHashCode()
{
int retval = base.GetHashCode();
return retval;
}
public override bool Equals(object obj)
{
if (obj == null)
return false;
MyType rhs = obj as MyType;
if ((Object)rhs == null)
return false;
return this == rhs;
}
public static bool operator ==(MyType lhs, MyType rhs)
{
bool result;
if ((Object)lhs != null && (Object)rhs != null)
result = lhs.Value == rhs.Value;
else
result = (Object)lhs == (Object)rhs;
return result;
}
public static bool operator !=(MyType lhs, MyType rhs)
{
return !(lhs == rhs);
}
}