Vous avez ce que vous croyez être un problème, cependant, si vous regardez leurs codes de hachage dans la même exécution , vous trouverez qu'ils ne sont pas identiques, mais plutôt s'appuyer sur leur ordre d'utilisation:
Console.WriteLine("{0} {1:08X}", typeof(string), typeof(string).GetHashCode());
Console.WriteLine("{0} {1:08X}", typeof(Program), typeof(Program).GetHashCode());
// System.String 02BF8098
// Program 00BB8560
Si je l'exécuter à nouveau le programme, la permutation de leur ordre:
Console.WriteLine("{0} {1:08X}", typeof(Program), typeof(Program).GetHashCode());
Console.WriteLine("{0} {1:08X}", typeof(string), typeof(string).GetHashCode());
// Program 02BF8098
// System.String 00BB8560
C'est un non-problème lors de l'exécution que les valeurs renvoyées à ne pas violer les règles de mise en œuvre de Object.GetHashCode
.
Mais, comme vous l'avez remarqué ce comportement semble curieux!
J'ai fouillé dans la source et a constaté la mise en œuvre de l' Type.GetHashCode
est imposée sur MemberInfo.GetHashCode
, qui est de nouveau imposé sur Object.GetHashCode
qui demande RuntimeHelpers.GetHashCode(this)
.
C'est à ce moment que la piste va froid, cependant, mon hypothèse, c'est le fonctionnement interne de cette méthode crée une nouvelle valeur, cartographiée par exemple, basé sur l'ordre des appels.
J'ai testé cette hypothèse en exécutant le code ci-dessus avec deux instances de l' Program
(après l'ajout d'une propriété à les identifier):
var b = new Program() { Name = "B" };
var a = new Program() { Name = "A" };
Console.WriteLine("{0} {1:08X}", a.Name, a.GetHashCode());
Console.WriteLine("{0} {1:08X}", b.Name, b.GetHashCode());
// A 02BF8098
// B 00BB8560
Ainsi, pour les classes qui ne sont pas explicitement remplacent Object.GetHashCode
, les instances seront attribués apparemment prévisible de la valeur de hachage basée sur l'ordre dans lequel ils appellent GetHashCode
.
Mise à jour: j'ai regardé comment Rotor/Shared Source CLI gère cette situation, et j'ai appris que le défaut de mise en œuvre de calcule et mémorise un code de hachage de la synchronisation de bloc pour l'instance de l'objet, assurant ainsi le code de hachage est généré qu'une seule fois. La valeur par défaut de calcul pour ce code de hachage est trivial, et utilise par thread de semences (emballage est le mien):
// ./sscli20/clr/src/vm/threads.h(938)
// Every thread has its own generator for hash codes so that we
// won't get into a situation where two threads consistently give
// out the same hash codes.
// Choice of multiplier guarantees period of 2**32
// - see Knuth Vol 2 p16 (3.2.1.2 Theorem A).
Donc, si le CLR suit cette mise en œuvre, il semblerait toutes les différences observées dans le code de hachage de valeurs pour les objets sont basés sur le domaine d'application et Géré Thread qui a créé l'instance.