12

This is mostly academic - but I was looking at the implementation of Equals() for ValueTypes. The source code is here: http://referencesource.microsoft.com/#mscorlib/system/valuetype.cs#38

The code that caught my eye was this:

    // 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() is declared as follows:

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

My understanding is that the '[MethodImplAttribute(MethodImplOptions.InternalCall)]' indicates that this is implemented in the CLR (source not available), but I thought I would be able to call it directly from my code. When I try, I get a SecurityException

ECall methods must be packaged into a system module.

Can I make these calls myself (or are they meant for internal consumption only)? If I can call them directly, what is the appropriate way of doing so?

Rob P.
  • 14,921
  • 14
  • 73
  • 109
  • Related: [SecurityException: ECall methods must be packaged into a system module](http://stackoverflow.com/questions/11286004/securityexception-ecall-methods-must-be-packaged-into-a-system-module) – Patrick Hofman May 20 '14 at 14:05
  • 2
    Why do you actually want to call it? – leppie May 20 '14 at 14:20
  • 3
    @leppie As per the question, this is merely academic, there is no practical application in mind. – Servy May 20 '14 at 14:25
  • 1
    The correct way of doing it? By calling `.Equals(` on a value type. – Scott Chamberlain May 20 '14 at 14:37
  • 3
    FWIW, you *can* see the implementation of `FastEqualsCheck`, or the (almost) CLR 2.x version, by looking at the SSCLI [sources](http://www.microsoft.com/en-us/download/details.aspx?id=4917). [Another answer](http://stackoverflow.com/a/2741426/21567) on SO has more details and some code. – Christian.K May 20 '14 at 17:51
  • 1
    How do you actually do the call, and under what context? I was able to call the method after creating a delegate to it fine from a LINQPad script as well as a basic console program. – Jeff Mercado May 21 '14 at 00:59

1 Answers1

7

You cannot call these methods yourself. They are internal and can only be called by methods that are in the same assembly. This is exactly what the exception tells you.

As suggested in the comments, you can look through the SSCLI code for the actual implementation.

This blog post tells you exactly where to find it:

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

And the download link to the SSCLI source code:

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

The actual implementation is as following:

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);
}

As you can see, they simply perform a memcmp. So, what you could do is create a function like this in a unmanged DLL and call that, which is essentially the same.

Swen Kooij
  • 985
  • 1
  • 8
  • 18