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])始めた行にありました。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私はC ++の専門家ではないので、この実装がメソッドを呼び出す前にnullチェックを実行しない理由を誰かが説明できますCompareTo()か?Equals()とOperator ==のオーバーロードに関するMSDNガイドラインによると内で何かを実行する前に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チェックを実行しない理由を私に説明できますか

それを書いた人は誰でもヌルをチェックすることを怠ったからです。

そのような予測できない動作につながる使用法の欠陥はおそらくありますか?

ええと、nullポインタを何かと比較することはおそらくエッジケースですが、私は確かにそれを「欠陥」とは呼びません。の実装==が正しくありません。

この問題を回避するには、同等性チェックを逆にしたり、次のチェックを行ったりしnullます。

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