List sorting issue in c#
public static List<PreviewSchedule> BuildPreviewSchedule(Chatham.Business.Objects.Transaction transaction)
{
List<PreviewSchedule> items = new List<PreviewSchedule>();
List<ScheduleItem> scheduleItems = new List<ScheduleItem>(transaction.ScheduleCollection.FindAll(row => row.IsDeleted == false));
bool allFromDateFilledIn = !scheduleItems.Exists(item => !item.FromDate.HasValue);
bool allFloatingFromDateFilledIn = !scheduleItems.Exists(item => !item.FloatingFromDate.HasValue);
scheduleItems.Sort((a, b) => a.FromDate.GetValueOrDefault().CompareTo(b.FromDate.GetValueOrDefault()));
scheduleItems.Sort((a, b) => SortIt(a, b, allFromDateFilledIn, allFloatingFromDateFilledIn));
for (int i = 0; i < scheduleItems.Count; i++)
{
items.Add(new PreviewSchedule
{
Drop = i == 0 ? "$0.00" :
((scheduleItems[i - 1].PrincipalNotionalAmount - scheduleItems[i].PrincipalNotionalAmount)).Value.ToString(Format.CurrencyCentsIncludedFormatStringDollarSign),
EndDate = GetDateOrNull(scheduleItems[i].ToDate),
StartDate = GetDateOrNull(scheduleItems[i].FromDate),
Notional = scheduleItems[i].PrincipalNotionalAmount.Value.ToString(Format.CurrencyCentsIncludedFormatStringDollarSign),
FloatingEndDate = GetDateOrNull(scheduleItems[i].FloatingToDate),
FloatingStartDate = GetDateOrNull(scheduleItems[i].FloatingFromDate)
});
}
return items;
}
Here is the method that we call to return our schedule to the front end in our mvc app. Now, this list has been mixing up the last two rows on a specific model the same way each time. Look at the pic:
Last two rows of the table, you can obviously see the last two rows are switched around, because the dates don't follow each other. This method is spitting back those mixed up dates, and I'm thinking it's a problem with the sorting. Can any of you guys see where the sorting would cause this?
Thanks ahead of time.
Edit:
SortIt() code:
private static int SortIt(
Chatham.Business.Objects.ScheduleItem a,
Chatham.Business.Objects.ScheduleItem b,
bool allFromDateFilledIn,
bool allFloatingFromDateFilledIn)
{
return SortIt(a.FromDate, a.FloatingFromDate, b.FromDate, b.FloatingFromDate, allFromDateFilledIn, allFloatingFromDateFilledIn);
}
private static int SortIt(DateTime? aFrom,
DateTime? aFloatingFrom,
DateTime? bFrom,
DateTime? bFloatingFrom,
bool allFromDateFilledIn,
bool allFloatin开发者_如何学JAVAgFromDateFilledIn)
{
DateTime? a = null;
DateTime? b = null;
if (allFromDateFilledIn == false && allFloatingFromDateFilledIn == false)
{
a = aFrom ?? aFloatingFrom;
b = bFrom ?? bFloatingFrom;
}
else
{
a = allFromDateFilledIn ? aFrom : aFloatingFrom;
b = allFromDateFilledIn ? bFrom : bFloatingFrom;
}
if (a.HasValue && b.HasValue)
return a.Value.CompareTo(b.Value);
return 0;
}
I notice the second-to-last row is the only one that has all four dates filled in. I also notice that 01-Oct-2013 is before 01-Nov-2013. I strongly suspect those are the dates being compared together. I can't completely diagnose or correct the issue without knowing what the SortIt
method looks like, though. Regardless, that's probably the source of your problem, so I'd focus your efforts there.
Consider what should happen when all four dates are filled in, and figure out how to handle that case.
Edit:
Now that you've added the SortIt
code, take a look at your allFromDateFilledIn
and allFloatingFromDateFilledIn
flags. Both of these are always going to be false with your example data, because both the From and FloatingFrom columns contain at least one null cell somewhere. Therefore, your SortIt
method is always going to evaluate this:
a = aFrom ?? aFloatingFrom;
b = bFrom ?? bFloatingFrom;
...which means comparing values from different columns together. It also means that when both From and FloatingFrom exist, From always wins as the comparison value.
Edit 2:
You could try replacing the above with an inner if/else
like this:
if (aFrom != null && bFrom != null)
{
a = aFrom;
b = bFrom;
}
else if (aFloatingFrom != null && bFloatingFrom != null)
{
a = aFloatingFrom;
b = bFloatingFrom;
}
else
{
a = aFrom ?? aFloatingFrom;
b = bFrom ?? bFloatingFrom;
}
I feel like maybe that logic could be reduced/prettified, but it seems easiest to understand this way. Note that From still has higher priority than FloatingFrom.
You might want to consider what your boolean flags are doing, as well. They'll only come into play when one or the other column is completely full, in which case they'll lock-in that column as the comparison column. That may be what you want, or it may be unnecessary. You've already established that From takes precedence over FloatingFrom, so without a reason to override that rule, I'd just follow it for the sake of consistency. Just a thought.
There is a problem here:
if (a.HasValue && b.HasValue)
return a.Value.CompareTo(b.Value);
return 0;
This can give inconsistent return values when either a
or b
doesn't have a value. Imagine if the sort method calls this with a=2011/04/24
and b=null
. It's going to return 0. Later in the same sort, it might be called with a=null
and b=2011/03/24
. In both cases, the method will return 0.
The behavior of List.Sort
when the comparison method returns inconsistent values is undefined. Here you have a case where, given three values (I'll use numbers, but the same will hold true for dates), you can't give a reliable sort.
a = 5
b = 10
c = null
Comparing a
and c
returns 0. Comparing b
and c
returns 0, as well. One assumes that if a==c
and b==c
, then a==b
. But in this case a < b
. This is going to cause Sort
to behave unpredictably. Some sorting methods will go into an infinite loop in this situation, or crash.
精彩评论