Voici l’exemple avec commentaires :
Alors, que pensez-vous à ce sujet ?
Voici l’exemple avec commentaires :
Alors, que pensez-vous à ce sujet ?
Le bug est dans les deux lignes suivantes de l' System.ValueType
: (je suis entré dans la source de référence)
if (CanCompareBits(this))
return FastEqualsCheck(thisObj, obj);
(Les deux méthodes sont [MethodImpl(MethodImplOptions.InternalCall)]
)
Lorsque tous les champs sont de 8 octets, CanCompareBits
, à tort, renvoie true, résultant en un bit à bit de comparaison de deux différents, mais sémantiquement identiques, les valeurs.
Lorsque au moins un des champs n'est pas 8 octets de large, CanCompareBits
retourne false, et le code de produit à utiliser la réflexion pour une boucle sur les champs et appelez - Equals
pour chaque valeur, qui traite correctement -0.0
comme égal à 0.0
.
Voici la source pour CanCompareBits
de SSCLI:
FCIMPL1(FC_BOOL_RET, ValueTypeHelper::CanCompareBits, Object* obj)
{
WRAPPER_CONTRACT;
STATIC_CONTRACT_SO_TOLERANT;
_ASSERTE(obj != NULL);
MethodTable* mt = obj->GetMethodTable();
FC_RETURN_BOOL(!mt->ContainsPointers() && !mt->IsNotTightlyPacked());
}
FCIMPLEND
J'ai trouvé la réponse à http://blogs.msdn.com/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx.
Le coeur est la source de commenter CanCompareBits
, ValueType.Equals
utilise pour déterminer s'il faut utiliser memcmp
-style de comparaison:
Le commentaire de CanCompareBits dit "Retourne true si la valuetype n' contenir pointeur et est étroitement emballé". Et FastEqualsCheck utilisation "comparateur de mémoire" pour accélérer la comparaison.
L'auteur poursuit en affirmant exactement le problème décrit par l'OP:
Imaginez que vous avez une structure qui ne contient qu'un float. Ce qui va se produire si l'un contient +0.0, et les autres contient -0.0? Ils devraient être les de même, mais le sous-jacent binaire représentation sont différents. Si vous nid d'une autre structure, qui l'emportent la méthode Equals, que l'optimisation échoueront également.
Vilx la conjecture est correcte. Ce "CanCompareBits" ne se vérifie pour voir si le type de la valeur en question est "serrée" dans la mémoire. Une serrés struct est comparé en comparant simplement les bits binaires de la structure; un vaguement emballé structure est comparée en appelant est Égal pour tous les membres.
C'est ce qui explique SLaks' observation, qu'il repros avec les structures qui sont toutes des chambres doubles; ces structures sont toujours serrés.
Malheureusement, comme nous l'avons vu ici, qui introduit une différence sémantique, car au niveau du bit de comparaison de doubles et correspond à la comparaison des doubles donne des résultats différents.
La moitié d’une réponse :
Réflecteur nous dit que `` fait quelque chose comme ceci :
Malheureusement les deux et
(les deux méthodes statiques) sont extern ( `` ) et n’ont aucune source disponible.
Retour à deviner pourquoi un cas peut être comparé par bits, et l’autre ne peut (alignement des questions peut-être ?)
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.