Требование равенства словаря C # - PullRequest
5 голосов
/ 06 января 2012

Должны ли ключи Dictionary быть сопоставимы с равенством?

Например

Class mytype
{
    public bool equals(mytype other)
    {
        return ...;
    }
}

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

Если мне нужно реализовать равенство, нужно ли иметь большое числовое значение, которое увеличивается с каждым новым созданным экземпляром mytype?

Ответы [ 5 ]

3 голосов
/ 06 января 2012

Если ваши классы только equal, если они одного экземпляра, вам не нужно ничего делать, чтобы использовать их в Dictionary.Классы (ссылочные типы) считаются равными тогда и только тогда, когда они ссылаются на один и тот же объект.

Из документации GetHashCode

Для производных классов Objectметод GetHashCode может делегировать реализации Object.GetHashCode, если и только если этот производный класс определяет равенство значений как равенство ссылок, а тип не является типом значения.

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

2 голосов
/ 06 января 2012

Только если они используются в качестве ключа и вы не хотите основывать эквивалентность на экземпляре самого объекта. Если вы хотите, чтобы ссылки на точно такой же экземпляр были эквивалентными, у вас все в порядке и вам ничего не нужно делать, но если вы используете свой тип в качестве ключа и хотите, чтобы «эквивалентные» экземпляры считались равными, ваш класс должен реализовать Equals() и GetHashCode().

Если ваш пользовательский тип хранится как значение и не используется в качестве ключа, это, разумеется, не обязательно. Например, в этом случае MyType не нужно переопределять Equals() или GetHashCode(), поскольку он используется только как значение, а не как ключ хранения.

Dictionary<string, MyType> x;

Однако в этом случае:

Dictionary<MyType, string> x;

Ваш пользовательский тип является ключом, и поэтому он должен переопределить Equals() и GetHashCode(). GetHashCode() используется для определения местоположения, в котором он хэшируется, а Equals() используется для разрешения коллизий в хэш-коде (среди прочего).

Вам нужно будет переопределить два одинаковых метода, когда вы также имеете дело со многими LINQ запросами. Кроме того, вы можете предоставить отдельную IEqualityComparer отдельно от вашего класса, чтобы определить, эквивалентны ли два экземпляра.

2 голосов
/ 06 января 2012

По умолчанию равенство основано на экземпляре. Два отдельных экземпляра никогда не равны. Вы можете изменить это только предоставив собственный метод Equals.

1 голос
/ 06 января 2012

См. Свойство EqualityComparer.Default .Вот как словарь получает средство сравнения на равенство, если вы его не предоставляете.

Возвращает средство сравнения на основе типа и возможностей T.

Например, если Tрасширяет IEquatable, EqualityComparer.Default будет возвращать экземпляр средства сравнения равенства, который использует интерфейс IEquatable.В противном случае он вернет экземпляр средства сравнения равенства, в котором используется метод Object.Equals.

Метод Object.Equals по умолчанию для ссылочных типов использует равенство ссылок (Object.ReferenceEquals), если только вы не переопределите его пользовательским сравнением..

Метод Object.Equals по умолчанию для типов значений использует отражение для сравнения полей структуры на равенство *.Отражение медленное, поэтому всегда рекомендуется переопределять Equals в типах значений.

*, за исключением случаев, когда это тип blittable, и в этом случае сравниваются необработанные биты.

0 голосов
/ 06 января 2012

Нет, нет ограничений типа на Dictionary<TKey, TValue>

...