1

我有一个没有实现IComparable接口的 .NET 类。在我在这个类上实现IComparable接口之后,一些使用我的类的 c++ 代码意外地改变了它的行为。现在它抛出一个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])开始使用IComparableimplementation 执行==操作的行中!

原因是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:我不是 c++ 专家,所以有人可以解释一下为什么这个实现_Left在调用CompareTo()方法之前不执行 null 检查吗?根据MSDN Guidelines for Overloading Equals() 和 Operator == null 检查必须在操作员内部执行任何==操作之前完成。

 ...
 // 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:是否存在导致这种不可预测行为的使用缺陷?

4

1 回答 1

2

所以有人可以解释一下为什么这个实现在调用 CompareTo() 方法之前不对 _Left 执行空检查

因为写它的人忽略了检查空值。

使用中是否可能存在一些缺陷导致这种不可预测的行为?

好吧,将空指针与某物进行比较可能是一种极端情况,但我当然不会称其为“缺陷”。的实现==不正确。

要解决此问题,您可以反转您的平等检查和/或检查null

if (unitNames[i] == nullptr)
  dwRet = BUMC_NOT_COMPLETE;
于 2012-11-12T15:37:12.257 回答