Как я могу позвонить FastEqualsCheck()?

Это в основном академический, но я смотрел на реализацию Equals() для ValueTypes. Исходный код здесь: http://referencesource.microsoft.com/#mscorlib/system/valuetype.cs#38

Код, который попался мне на глаза, был следующим:

    // if there are no GC references in this object we can avoid reflection 
    // and do a fast memcmp
    if (CanCompareBits(this))
        return FastEqualsCheck(thisObj, obj);

FastEqualsCheck() объявляется следующим образом:

[System.Security.SecuritySafeCritical]  
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern bool FastEqualsCheck(Object a, Object b);

Я понимаю, что '[MethodImplAttribute (MethodImplOptions.InternalCall)] указывает, что это реализовано в CLR (источник недоступен), но я думал, что смогу называть его непосредственно из моего кода. Когда я пытаюсь, я получаю SecurityException

ECall methods must be packaged into a system module.

Могу ли я самостоятельно совершать эти звонки (или они предназначены только для внутреннего потребления)? Если я могу назвать их напрямую, каков подходящий способ сделать это?

Ответ 1

Вы не можете сами называть эти методы. Они internal и могут быть вызваны только теми методами, которые находятся в одной и той же сборке. Это именно то, что говорит вам исключение.

Как указано в комментариях, вы можете просмотреть код SSCLI для фактической реализации.

В этом блоге вы узнаете, где его найти:

http://blogs.msdn.com/b/xiangfan/archive/2008/09/01/magic-behind-valuetype-equals.aspx

И ссылка для загрузки в исходный код SSCLI:

http://www.microsoft.com/en-us/download/details.aspx?id=4917

Фактическая реализация такова:

FCIMPL2(FC_BOOL_RET, ValueTypeHelper::FastEqualsCheck, Object* obj1,
    Object* obj2)
{
    WRAPPER_CONTRACT;
    STATIC_CONTRACT_SO_TOLERANT;

    _ASSERTE(obj1 != NULL);
    _ASSERTE(obj2 != NULL);
    _ASSERTE(!obj1->GetMethodTable()->ContainsPointers());
    _ASSERTE(obj1->GetSize() == obj2->GetSize());

    TypeHandle pTh = obj1->GetTypeHandle();

    FC_RETURN_BOOL(memcmp(obj1->GetData(),obj2->GetData(),pTh.GetSize()) == 0);
}

Как вы можете видеть, они просто выполняют memcmp. Итак, что вы можете сделать, так это создать такую ​​функцию в неиспользуемой DLL и вызвать это, что по сути одно и то же.