STL/CLR Library uses IComparable to implement == operator and throws NullReferenceException

StackOverflow https://stackoverflow.com/questions/13346081

  •  28-11-2021
  •  | 
  •  

Question

I had a .NET class which was not implementing IComparable interface. After I implemented IComparable interface on this class some c++ code using my class changed it's behavior unexpectedly. Now it throws a NullReferenceException

DWORD UnitsAdapter::GetUnitNames([Out]array<MyClass^>^% unitNames)
{

  ...

  unitNames = gcnew array<MyClass^>(10);

  DWORD dwRet = BUMC_OK;
  for (int i = 0; i < unitNames->Length; ++i)
  {
    unitNames[i] = nullptr;
    unitNames[i] = CoCliUnitsHelper::getUnitName(unitIds[i]);

    if (nullptr == unitNames[i])
      dwRet = BUMC_NOT_COMPLETE;
  }

  return dwRet;

}

The problem was in the line if (nullptr == unitNames[i]) which started using IComparable implementation to perform == operation!

The reason was a template from cliext utility header file.

//
// System::IComparable TEMPLATE COMPARISONS
//
template<typename _Value_t>
    bool operator==(System::IComparable<_Value_t>^ _Left,
        System::IComparable<_Value_t>^ _Right)
    {   // test if _Left == _Right
    return (_Left->CompareTo(_Right) == 0);
    }

Question 1: I am not a c++ expert, so can someone explain me why this implementation does not perform a null check on _Left before calling CompareTo() method ? According to MSDN Guidelines for Overloading Equals() and Operator == null checks must be done prior of doing anything inside == operator.

 ...
 // If both are null, or both are same instance, return true.
 if (System.Object.ReferenceEquals(a, b))
 {
        return true;
 }

 // If one is null, but not both, return false.
 if (((object)a == null) || ((object)b == null))
 {
        return false;
 }
 ...

Question 2: Is there probably some flaw in usage which leads to such an unpredictable behavior?

Was it helpful?

Solution

so can someone explain me why this implementation does not perform a null check on _Left before calling CompareTo() method

Because whoever wrote it neglected to check for nulls.

Is there probably some flaw in usage which leads to such an unpredictable behavior?

Well, comparing a null pointer to something is probably an edge case, but I certainly wouldn't call it a "flaw". The implementation of == is incorrect.

To workaround this issue, you could reverse your equality check and/or check for null:

if (unitNames[i] == nullptr)
  dwRet = BUMC_NOT_COMPLETE;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top