c # — Библиотека STL / CLR использует IComparable для реализации оператора == и выдает исключение NullReferenceException

У меня был класс .NET, который не был реализован IComparable интерфейс.
После того, как я реализовал IComparable В интерфейсе этого класса некоторый код на С ++, использующий мой класс, неожиданно изменил свое поведение. Теперь это бросает 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;

}

Проблема была в линии if (nullptr == unitNames[i]) который начал использовать IComparable реализация для выполнения == работа!

Причиной был шаблон от cliext служебный заголовочный файл.

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

Вопрос 1: Я не эксперт по С ++, поэтому кто-то может объяснить мне, почему эта реализация не выполняет нулевую проверку _Left перед звонком CompareTo() метод? В соответствии с Рекомендации MSDN по перегрузке Equals () и 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;
}
...

Вопрос 2: Есть ли какой-то недостаток в использовании, который приводит к такому непредсказуемому поведению?

1

Решение

поэтому кто-то может объяснить мне, почему эта реализация не выполняет нулевую проверку _Left перед вызовом метода CompareTo ()

Потому что тот, кто написал это, пренебрегал проверкой на нулевые значения.

Есть ли какой-то недостаток в использовании, который приводит к такому непредсказуемому поведению?

Что ж, сравнение нулевого указателя с чем-то, вероятно, является крайним случаем, но я бы не назвал это «недостатком». Реализация == это неверно.

Чтобы обойти эту проблему, вы можете отменить проверку на равенство и / или проверить null:

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

Другие решения

Других решений пока нет …