La principale confusion ici est que vous supposez que toutes les bibliothèques .NET (dans ce cas, la bibliothèque numérique étendue, qui ne fait pas partie de la BCL) sont écrites en C # standard. Ce n'est pas toujours le cas et différentes langues ont des règles différentes.
En C # standard, le morceau de code que vous voyez entraînerait un débordement de pile, en raison du fonctionnement de la résolution de surcharge des opérateurs. Cependant, le code n'est pas réellement en C # standard - il utilise essentiellement des fonctionnalités non documentées du compilateur C #. Au lieu d'appeler l'opérateur, il émet ce code:
ldarg.0
ldarg.1
ceq
ret
Voilà :) Il n'y a pas de code C # 100% équivalent - ce n'est tout simplement pas possible en C # avec votre propre type.
Même dans ce cas, l'opérateur réel n'est pas utilisé lors de la compilation de code C # - le compilateur fait un tas d'optimisations, comme dans ce cas, où il remplace l' op_Equality
appel par le simple ceq
. Encore une fois, vous ne pouvez pas répliquer cela dans votre propre DoubleEx
structure - c'est la magie du compilateur.
Ce n'est certainement pas une situation unique dans .NET - il y a beaucoup de code qui n'est pas valide, C # standard. Les raisons sont généralement (a) des hacks de compilateur et (b) un langage différent, avec les hacks d'exécution impairs (c) (je vous regarde Nullable
,!).
Étant donné que le compilateur Roslyn C # est une source oepn, je peux en fait vous indiquer l'endroit où la résolution de surcharge est décidée:
L'endroit où tous les opérateurs binaires sont résolus
Les "raccourcis" pour les opérateurs intrinsèques
Lorsque vous regardez les raccourcis, vous verrez que l'égalité entre double et double se traduit par l'opérateur double intrinsèque, jamais par l' ==
opérateur réel défini sur le type. Le système de types .NET doit prétendre que Double
c'est un type comme les autres, mais pas C # - double
est une primitive en C #.