Reputation: 23300
I'm attempting to implement a sorting mechanism in one of my views, but it looks like OrderBy
can't handle "big" (more below) integer fields, ending up in a messed up order.
Here is all the code involved, stripped down as much as possible:
Models:
public class MyModel
{
public MyOption Option { get; set; }
}
public class MyOption
{
public int Value {get; set;}
public string Descr{get; set;}
}
DisplayTemplates\MyOption
@model MyOption
@Html.Label(Model.Description)
Controller's returning view:
@model List<MyModel>
<ul>
@foreach(var row in Model)
{
<li>@Html.DisplayFor(x => row.Option)</li>
}
</ul>
Controller:
private List<MyModel> FakeRetrieveFromRepo()
{
return new List<MyModel>
{
new MyModel { Option = new MyOption { Value = 121370002, Descr = "One" }},
new MyModel { Option = new MyOption { Value = 121370000, Descr = "Two" }},
new MyModel { Option = new MyOption { Value = 121370001, Descr = "Three" }},
};
// Debugging confirms this order is kept
}
public ActionResult Index()
{
List<MyModel> data = FakeRetrieveFromRepo();
// "Offending" line: sorting is supposed to be done here
// neither .Option nor .Option.Value can be null
data = data.OrderBy(row => row.Option.Value).ToList();
// I expect the list to be sorted in this fashion
// [ {Option={ Value = 121370000, Descr = "Two" }},
// {Option={ Value = 121370001, Descr = "Three" }},
// {Option={ Value = 121370002, Descr = "One" }} ]
return View(data);
}
If I try and sort like this, no sorting actually takes place, data in the view is in the same order in which it was provided by the repository. If I change that line like this, magically the sorting happens and gives me the expected result:
// If I change the line like this, sorting takes place!
data = data.OrderBy(row => row.Option.Value % 121370000).ToList();
I'm well used to implementing obscure workarounds to make stuff work, but it looks like there's something I don't know here: it seems like OrderBy
only handles small numbers correctly ?
Upvotes: 1
Views: 94
Reputation: 1062755
I've reduced the code in the question to the following - and it works absolutely fine; .NET can work perfectly well with large numbers. So that leaves us with the most likely answer that the problem is not in the example - simplifying code is great, but you need to find a minimal runnable example that shows the problem. Most times, when trying to get a minimal repro, the very act of finding "what is different between my example code, and my real code" will tell you what the problem is. Unfortunately, we can't do that for you, because we can't see the real code.
The following works fine:
static void Main()
{
var data = FakeRetrieveFromRepo();
// order here is "One", "Two", "Three"
data = data.OrderBy(row => row.Option.Value).ToList();
// order here is "Two", "Three", "One"
}
private static List<MyModel> FakeRetrieveFromRepo()
{
return new List<MyModel>
{
new MyModel { Option = new MyOption {
Value = 121370002, Description = "One" }},
new MyModel { Option = new MyOption {
Value = 121370000, Description = "Two" }},
new MyModel { Option = new MyOption {
Value = 121370001, Description = "Three" }},
};
}
Purely as an aside, assuming you don't need to leave the original list alone (caching, etc) - an in-place sort is more efficient:
data.Sort((x, y) => x.Option.Value.CompareTo(y.Option.Value));
Upvotes: 6