2017-03-15 38 views
-1

私はtblDetailオブジェクトのリストを持っています。 tblDetailsには文字列txtTrackedがあります。私はこのプロパティに基づいてソートしたい。だから私は:List.Sort私のIComparerが矛盾していると主張する

switch (sortby) 
{ 
    //... 
    case "Tracked Y/N": 
     list.Sort((lhs, rhs) => { 
      return lhs.txtTracked.CompareTo(rhs.txtTracked); 
     }); 
     break; 
    case "Tracked Y/N-desc": 
     list.Sort((lhs, rhs) => { 
      return -lhs.txtTracked.CompareTo(rhs.txtTracked); 
     }); 
     break; 
    //... 
} 

時々txtTrackedはnullを除いて。罰金、[OK]をので、私は実行します。

switch (sortby) 
{ 
    //... 
    case "Tracked Y/N": 
     list.Sort((lhs, rhs) => { 
      string toCompare = lhs.txtTracked; 
      if (toCompare == null) 
       toCompare = ""; 
      return toCompare.CompareTo(rhs.txtTracked); 
     }); 
     break; 
    case "Tracked Y/N-desc": 
     list.Sort((lhs, rhs) => { 
      string toCompare = lhs.txtTracked; 
      if (toCompare == null) 
       toCompare = ""; 
      return -toCompare.CompareTo(rhs.txtTracked); 
     }); 
     break; 
    //... 
} 

定期昇順ソート正常に動作しますが、私は同じデータセットに降順の並べ替えでこれを行う際に、何らかの理由で、私はでLHSにnull参照の例外を取得"追跡されたY/N-desc"。私はない:

switch (sortby) 
{ 
    //... 
    case "Tracked Y/N": 
     list.Sort((lhs, rhs) => { 
      string toCompare = lhs.txtTracked; 
      if (toCompare == null) 
       toCompare = ""; 
      return toCompare.CompareTo(rhs.txtTracked); 
     }); 
     break; 
    case "Tracked Y/N-desc": 
     //for some reason this sort adds null into the list. wat. 
     list.Sort((lhs, rhs) => { 
      if (lhs == null) 
       return 1; 
      if (rhs == null) 
       return -1; 
      string toCompare = lhs.txtTracked; 
      if (toCompare == null) 
       toCompare = ""; 
      return -toCompare.CompareTo(rhs.txtTracked); 
     }); 
     list.RemoveAll(d => d == null); 
     break; 
    //... 
} 

今だけ私は新しいエラーを取得する:

Unable to sort because the IComparer.Compare() method returns inconsistent results. Either a value does not compare equal to itself, or one value repeatedly compared to another value yields different results. 

与えるもの?それは一方的な方法ではなく、他方の方法ではうまく機能します。私のソート機能が十分ではないとC#がどのように判断し、どうすれば正しいのですか?

そして、私が並べ替えを呼び出すと、なぜ私のリストにnullが追加されるのですか?

+1

lhsとrhsの両方がヌルの場合、0を返し、1のように戻らなくてはなりません。 – Evk

+2

'CompareTo'の結果を否定することは、ソートを元に戻す確実な方法ではありません。 'int.MinValue'を正しく処理しません。ソートを元に戻すには、オペランドの順序を逆にする必要があります。 – Servy

答えて

1

これまでのところ、昇順ソートではnull参照例外がスローされなかったことは幸運でした。それとも、それがあなたの注意を引かなかったことは不運だったのでしょうか?

オブジェクトは1つ(またはそれ以上)がnullです。昇順ソートを使用したときにはrhsを、ソートを降順に使用したときは、ちょうど起き上がった。 CompareToメソッドがそれを処理するので、rhs == nullを持つのは大丈夫です。しかし、lhs == nullの場合、例外が発生します。

lhsとrhsの両方またはどちらか一方がヌルであることを可能にするヌルセーフメソッドが既にあります。スタティックString.Compare(String, String)です。昇順ソート用

list.Sort((lhs, rhs) => { return String.Compare(lhs?.txtTracked, rhs?.txtTracked); }); 

、および

list.Sort((lhs, rhs) => { return String.Compare(rhs?.txtTracked, lhs?.txtTracked); }); 

を降順の並べ替えのために:次のようにnull-safe navigation operator ?.と一緒に、このメソッドを使用することができます。

+1

@Adam:上の例では、[否定の誤った使用](https://stackoverflow.com/questions/42820101/list-sort-alleging-that-my-icomp-res-inconsistent#comment72752439_42820101)を逆にすることも回避していますソート順。 –

+1

しかし、この方法では、演算子 '?.'を使用して、' tblDetail'が「良い」インスタンス(つまり非正規表現)であるすべてのエントリの中で 'tblDetail'自体が' null)、その '.txtTracked'メンバは' null'に等しくなります。 –

+0

@JeppeStigNielsen良い点。 OPは、nullのlhsがnull rhs.txtTracked(rhsがnullでない場合)とどのように比較すべきかに関する決定をする必要があります。この答えでは、彼らは平等に扱われます。それが良いかどうかは、問題のドメインに依存します。 –

-1

descの変数を切り替えるようにしてください。

list.Sort((lhs, rhs) => { 
      return (rhs.txtTracked ?? "").CompareTo(lhs.txtTracked ?? ""); 
     }); 
+0

'rhs'自体(または' lhs'自体)が 'null'の場合、これはまだまだ爆発します。だから私はそれが質問に答えるとは思わない。あなたのコードが爆発しないときでさえ、 'txtTracked'が' null 'であるすべてのエントリと、 'txtTracked'が' '' 'であるエントリをすべて混合します。これは私たちが望むものではないかもしれません。 'null'と' '' 'は通常は等しいとみなされません。 –

1

あなたは:両方被比較がnullであれば、それは常に正の1を返しますので、

list.Sort((lhs, rhs) => { 
     if (lhs == null) 
      return 1; 
     if (rhs == null) 
      return -1; 
     // more cases 
    }); 

これは動作しません。だからソートアルゴリズムはそれを正しく得ることはできません。間違った順序であるため2つのnullが交換されると、それらは依然として間違った順序になります。

xと比較してyがゼロでない場合は、xと比べてyの符号が反対でなければなりません。

代わりにあなたができる:一方または両方がnullある場合には

list.Sort((lhs, rhs) => { 
     if (lhs == null || rhs == null) 
      return Comparer<object>.Default.Compare(rhs, lhs); 
     return string.Compare(rhs.txtTracked, lhs.txtTracked); 
    }); 

を、私は単純にオブジェクトとしてそれらを比較します。それは動作します。あなたはまた、別の方法でそれを書くことができます:

list.Sort((lhs, rhs) => { 
     if (lhs == null || rhs == null) 
      return (rhs != null).CompareTo(lhs != null); 
     return string.Compare(rhs.txtTracked, lhs.txtTracked); 
    }); 

この方法ではfalsetrueよりも小さいという事実を使用していました。

関連する問題