Основна плутанина тут полягає в тому, що ви припускаєте, що всі .NET-бібліотеки (в даному випадку розширена бібліотека чисел, яка не входить до складу BCL) написані в стандартному C #. Це не завжди так, і різні мови мають різні правила.
У стандартному C # фрагмент коду, який ви бачите, призведе до переповнення стека через те, як працює роздільна здатність оператора. Однак код насправді не є стандартним C # - він в основному використовує незадокументовані функції компілятора C #. Замість виклику оператора він видає цей код:
ldarg.0
ldarg.1
ceq
ret
Це все :) Немає 100% еквівалентного C # коду - це просто неможливо в C # з власним типом.
Навіть тоді фактичний оператор не використовується при компіляції коду C # - компілятор робить купу оптимізацій, як у цьому випадку, де він замінює op_Equality
виклик просто простим ceq
. Знову ж, ви не можете повторити це у власній DoubleEx
структурі - це магія компілятора.
Це, звичайно, не є унікальною ситуацією в .NET - є безліч код, який недійсний, стандартний C #. Причини, як правило, (а) компіляторські хаки та (б) інша мова, з непарними (в) хай-файлами (я дивлюся на вас Nullable
,!).
Оскільки компілятор Roslyn C # є початковим джерелом, я фактично можу вказати вам на місце вирішення роздільної здатності перевантаження:
Місце, де всі бінарні оператори вирішені
"Ярлики" для внутрішніх операторів
Якщо ви подивитесь на ярлики, ви побачите, що рівність між подвійними та подвійними результатами в внутрішньому подвійному операторі, ніколи в реальному ==
операторі, визначеному для типу. Система типу .NET повинна робити вигляд, що Double
такий тип, як і будь-який інший, але C # ні - double
це примітив у C #.