Как c# выясняет хэш-код для объекта?

Я только что создал функцию Firebase, которая запускается при создании документа Firestore (с правилами для записи только администратору). Затем используйте admin.auth (). CreateUser (), чтобы создать нового пользователя правильно.

export const createUser = functions.firestore
.document('newUsers/{userId}')
.onCreate(async (snap, context) => {
    const userId = context.params.userId;
    const newUser = await admin.auth().createUser({
        disabled: false,
        displayName: snap.get('displayName'),
        email: snap.get('email'),
        password: snap.get('password'),
        phoneNumber: snap.get('phoneNumber')
    });
    // You can also store the new user in another collection with extra fields
    await admin.firestore().collection('users').doc(newUser.uid).set({
        uid: newUser.uid,
        email: newUser.email,
        name: newUser.displayName,
        phoneNumber: newUser.phoneNumber,
        otherfield: snap.get('otherfield'),
        anotherfield: snap.get('anotherfield')
    });
    // Delete the temp document
    return admin.firestore().collection('newUsers').doc(userId).delete();
});
12
задан Community 23 May 2017 в 12:30
поделиться

6 ответов

Кажется, что у меня есть подсказка теперь.

Я думал, что KeyValuePair является ссылочным типом, но это не, это - структура. И таким образом, это использует ValueType. GetHashCode () метод. В MSDN для него говорится: "Одно или несколько полей производного типа используются для вычисления возвращаемого значения".

Если Вы возьмете реальный ссылочный тип в качестве "поставщика кортежа", Вы обманете словарь (или Вы...).

using System.Collections.Generic;

namespace csharp_tricks
{
    class Program
    {
        class MyClass
        {
            int keyValue;
            int someInfo;

            public MyClass(int key, int info)
            {
                keyValue = key;
                someInfo = info;
            }

            public override bool Equals(object obj)
            {
                MyClass other = obj as MyClass;
                if (other == null) return false;

                return keyValue.Equals(other.keyValue);
            }

            public override int GetHashCode()
            {
                return keyValue.GetHashCode();
            }
        }

        class Pair<T, R>
        {
            public T First { get; set; }
            public R Second { get; set; }
        }

        static void Main(string[] args)
        {
            var dict = new Dictionary<Pair<int, MyClass>, object>();

            dict.Add(new Pair<int, MyClass>() { First = 1, Second = new MyClass(1, 2) }, 1);

            //this is a pair of the same values as previous! but... no exception this time...
            dict.Add(new Pair<int, MyClass>() { First = 1, Second = new MyClass(1, 3) }, 1);

            return;
        }
    }
}
1
ответ дан 2 December 2019 в 19:00
поделиться

Не переопределяйте GetHashcode (), и Равняется () на изменяемых классах, только переопределите его на неизменных классах или структурах, еще при изменении объекта, используемого, как вводят, хеш-таблица не будет функционировать правильно больше (Вы не сможете получить значение, связанное с ключом после того, как ключевой объект был изменен),

Также хеш-таблицы не используют хэш-коды для идентификации объектов, они используют сами ключевые объекты в качестве идентификаторов, не требуется, что все ключи, которые используются для добавления записей в хеш-таблице, возвращают различные хэш-коды, но рекомендуется, чтобы они сделали, еще производительность страдает значительно.

14
ответ дан 2 December 2019 в 19:00
поделиться

Вот надлежащий Хеш, и реализации равенства для Квадратического кортежа (содержит 4 компонента кортежа внутри). Этот код гарантирует надлежащее использование этого определенного кортежа в HashSets и словарях.

Больше на предмете (включая исходный код) здесь.

Отметьте использование ключевого слова непроверенного (для предотвращения переполнения) и бросок NullReferenceException, если obj является пустым (как требуется базовым методом)

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj))
        throw new NullReferenceException("obj is null");
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != typeof (Quad<T1, T2, T3, T4>)) return false;
    return Equals((Quad<T1, T2, T3, T4>) obj);
}

public bool Equals(Quad<T1, T2, T3, T4> obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    return Equals(obj.Item1, Item1)
        && Equals(obj.Item2, Item2)
            && Equals(obj.Item3, Item3)
                && Equals(obj.Item4, Item4);
}

public override int GetHashCode()
{
    unchecked
    {
        int result = Item1.GetHashCode();
        result = (result*397) ^ Item2.GetHashCode();
        result = (result*397) ^ Item3.GetHashCode();
        result = (result*397) ^ Item4.GetHashCode();
        return result;
    }
}
public static bool operator ==(Quad<T1, T2, T3, T4> left, Quad<T1, T2, T3, T4> right)
{
    return Equals(left, right);
}


public static bool operator !=(Quad<T1, T2, T3, T4> left, Quad<T1, T2, T3, T4> right)
{
    return !Equals(left, right);
}
3
ответ дан 2 December 2019 в 19:00
поделиться

Проверьте это сообщение Brad Abrams и также комментарий Brian Grunkemeyer еще для некоторой информации о как объект. Работы GetHashCode. Кроме того, смотрите на первый комментарий к сообщению в блоге Ayande. Я не знаю, следуют ли текущие выпуски Платформы все еще этим правилам или если они на самом деле изменились, она как Brad подразумевала.

2
ответ дан 2 December 2019 в 19:00
поделиться

так, вероятно, это не будет знать о хэш-кодах, он - "дети".

Ваш пример, кажется, доказывает иначе :-) Хэш-код для ключа MyClass и значение 1 то же для обоих KeyValuePair. Реализация KeyValuePair должна использовать обоих Key и Value для его собственного хэш-кода

При продвижении класс словаря хочет уникальные ключи. Это использует хэш-код, предоставленный каждым ключом для понимания вещей. Помните, что время выполнения не звонит Object.GetHashCode(), но это называет GetHashCode () реализацией обеспеченный примером, который Вы приводите ему.

Рассмотрите более сложный случай:

public class HappyClass
{

    enum TheUnit
    {
        Points,
        Picas,
        Inches
    }

    class MyDistanceClass
    {
        int distance;
        TheUnit units;

        public MyDistanceClass(int theDistance, TheUnit unit)
        {
            distance = theDistance;

            units = unit;
        }
        public static int ConvertDistance(int oldDistance, TheUnit oldUnit, TheUnit newUnit)
        {
            // insert real unit conversion code here :-)
            return oldDistance * 100;
        }

        /// <summary>
        /// Figure out if we are equal distance, converting into the same units of measurement if we have to
        /// </summary>
        /// <param name="obj">the other guy</param>
        /// <returns>true if we are the same distance</returns>
        public override bool Equals(object obj)
        {
            MyDistanceClass other = obj as MyDistanceClass;
            if (other == null) return false;

            if (other.units != this.units)
            {
                int newDistance = MyDistanceClass.ConvertDistance(other.distance, other.units, this.units);
                return distance.Equals(newDistance);
            }
            else
            {
                return distance.Equals(other.distance);
            }


        }

        public override int GetHashCode()
        {
            // even if the distance is equal in spite of the different units, the objects are not
            return distance.GetHashCode() * units.GetHashCode();
        }
    }
    static void Main(string[] args)
    {

        // these are the same distance... 72 points = 1 inch
        MyDistanceClass distPoint = new MyDistanceClass(72, TheUnit.Points);
        MyDistanceClass distInch = new MyDistanceClass(1, TheUnit.Inch);

        Debug.Assert(distPoint.Equals(distInch), "these should be true!");
        Debug.Assert(distPoint.GetHashCode() != distInch.GetHashCode(), "But yet they are fundimentally different values");

        Dictionary<object, object> dict = new Dictionary<object, object>();

        dict.Add(new KeyValuePair<MyDistanceClass, object>(distPoint, 1), 1);

        //this should not barf
        dict.Add(new KeyValuePair<MyDistanceClass, object>(distInch, 1), 1);

        return;
    }

}

В основном... в случае моего примера, Вы хотели бы два объекта, которые являются тем же расстоянием для возвращения "true" для, Равняется, но возвратите различные хэш-коды.

-1
ответ дан 2 December 2019 в 19:00
поделиться

У меня больше нет книжной ссылки, и я должен буду найти его только для подтверждения, но я думал основной хеш по умолчанию, просто хешированный вместе все члены объекта. Это получило доступ к ним из-за способа, которым работал CLR, таким образом, это не было что-то, что Вы могли записать, а также они имели.

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

Править: Книга была В C# из Нажатия MS. Тот с Полотном пилы на покрытии. Автор провел много времени, объяснив, как вещи были реализованы в CLR, как язык перевел вниз в MSIL, ect. ect. Если можно найти книгу, это не плохое чтение.

Править: Сформируйте ссылку, если она похожа

Объект. GetHashCode () использует внутреннее поле в Системе. Класс объекта для генерации значения хэш-функции. Каждому созданному объекту присваивают ключ уникального объекта, сохраненный как целое число, когда он создается. Эти ключи запускаются в 1 и увеличивают каждый раз, когда новый объект любого типа создается.

Хм я предполагаю, что должен записать несколько своих собственных хэш-кодов, если я ожидаю использовать объекты в качестве ключей хеша.

0
ответ дан 2 December 2019 в 19:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: