2012-02-15 7 views
3

以下のようなオブジェクトの一覧(MyDataクラス)があり、LINQクエリを使用してSecondDateプロパティの制約を満たすものだけを取得し、すべてのプロパティに基づいてこの制約を満たすアイテム。LINQを使用してNullable値の並べ替え規則を実装する

public class MyData 
{ 
    public Nullable<DateTime> FirstDate {get; set;} 
    public DateTime SecondDate {get; set;} 
    public TimeSpan SimpleInterval {get; set;} 
    public double SimpleValue {get; set;} 
    ... 
} 

私は、次のクエリを書いたが、私はNullable <DateTime> FirstDateプロパティを処理する方法がわかりません。このプロパティがnullに設定されているアイテムは、このプロパティ以外のフィールドの値が同じでない別のアイテムよりも低い値にソートする必要があります。あなたはDateTime.MinValueに等しい任意のFirstDate性質を持っていない場合は、より多くの意図を表現することがnull合体演算子を、使用することができ、あるいは、

var items = from item in list 
     where ((now - item.SecondDate).TotalSeconds < threshold)) 
     orderby item.FirstDate.HasValue descending, 
       item.FirstDate.GetValueOrDefault() descending, 
       item.SecondDate descending, 
       item.SimpleInterval descending, 
       item.SimpleValue descending, 
     select item; 

// public static void main 
double threshold = ... // some initialization 
DateTime now = DateTime.Now; 
List<MyData> list = new List<MyData>(); 
... 
var items = from item in list 
      where ((now - item.SecondDate).TotalSeconds < threshold)) 
      orderby item.FirstDate descending 
      orderby item.SecondDate descending 
      orderby item.SimpleInterval descending 
      orderby item.SimpleValue descending 
      select item 

答えて

8

は、次の例のように、HasValueプロパティを使用することができます。

orderby item.FirstDate.HasValue descending, 
     item.FirstDate.GetValueOrDefault() descending 

クエリ式で複数のorderby句を使用することがほぼ確実であることに注意してくださいないあなたが何をしたいのか - あなたの検索は、おそらく次のようになります。

var items = from item in list 
      where ((now - item.SecondDate).TotalSeconds < threshold)) 
      orderby item.FirstDate.HasValue descending, 
        item.FirstDate.GetValueOrDefault() descending, 
        item.SecondDate descending, 
        item.SimpleInterval descending, 
        item.SimpleValue descending 
      select item; 

注これは良い一般 - であることデータ内のすべてのものよりも低い/高いデフォルト値に依存しないため、目的のソリューションです。 default(DateTime)は実際にはDateTime.MinValueと同じですが、IMOには依存しない方がいいですが、「最初にヌルでバケットしたい、それから値をバケットに入れたい」と言っています。また、ヌル以外のデータは、ヌル以外のデータの前にソートされています。ヌルでない場合はDateTime.MinValueの値がです。

現在のクエリでは、それはタイブレーカーとしてのみ使用するのではなく、フィールドで新しい(安定した)ソートを効果的に実行しています。あなたの前のクエリは、あなたが望んでいた何を与えていた場合(それがあったように)、あなたは順序の順序を逆にする必要があります

var items = from item in list 
      where ((now - item.SecondDate).TotalSeconds < threshold)) 
      orderby item.SimpleValue descending, 
        item.SimpleInterval descending, 
        item.SecondDate descending, 
        item.FirstDate.HasValue descending, 
        item.FirstDate.GetValueOrDefault() descending 
      select item; 

連続orderby条項は基本的に、ほとんど常に間違いです。

+0

'default(DateTime)'は 'DateTime.MinValue'と等しいので、' HasValue'呼び出しはこの状況で冗長ではありませんか? –

+0

@ rich.okelly:いいえ、1つは、すべてのnull結果の前にすべてのnullでない 'DateTime.MinValue'結果を正しくソートします。 *おそらく*このようなnull以外の結果はありませんが、私のコードは一般的な方法で要件を満たしています。 –

+0

本当に、そのチェックは、私がそれを削除する前に私の元の答えにあったそれは不必要だった...私の悪いと確信していた! –

3

あなたがGetValueOrDefault methodを使用することができますはっきり:

var items = from item in list 
     where ((now - item.SecondDate).TotalSeconds < threshold)) 
     orderby item.FirstDate ?? DateTime.MinValue descending, 
       item.SecondDate descending, 
       item.SimpleInterval descending, 
       item.SimpleValue descending 
     select item; 
関連する問題