I have a list of objects similar to the one below (MyData class) and I would use a LINQ query to get only those that meet a constraint on SecondDate property, and finally sort the items that meet this constraint on the basis of all properties.
public class MyData
{
public Nullable<DateTime> FirstDate {get; set;}
public DateTime SecondDate {get; set;}
public TimeSpan SimpleInterval {get; set;}
public double SimpleValue {get; set;}
...
}
I wrote the following query, but I do not know how to handle the Nullable <DateTime> FirstDate property. An item which has this property set to null should be sorted lower than another item which has identical values of the fields except this property set to a not null value.
// 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
You can use the HasValue property, for example:
orderby item.FirstDate.HasValue descending,
item.FirstDate.GetValueOrDefault() descending
Note that using multiple orderby clauses in a query expression is almost certainly not what you want to do - your query should probably be:
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;
Note that this is a good general-purpose solution, because it doesn't rely on the default value being lower / higher than anything in your data. default(DateTime) is actually equal to DateTime.MinValue in reality, but IMO it's nice not to rely on that, but separately say "I first want to bucket by null vs non-null, then the value". It also means that the non-null data is sorted before the null data even if there are non-null DateTime.MinValue values.
In your current query, it's effectively performing a new (stable) sort on each field, rather than only using it as a tie-breaker. If your previous query was giving you what you wanted, then you should reverse the order of the orderings (as it were):
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;
Consecutive orderby clauses are almost always a mistake, basically.
You can use the GetValueOrDefault method:
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;
Alternatively, if you will not have any FirstDate properties equal to DateTime.MinValue, you could use the null coalescing operator, which may express the intent more clearly:
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With