.NET 5.0 关于 IEnumerable<T>.OrderBy 字符串比较行为的重大更改
.NET 5.0 breaking changes regarding `IEnumerable<T>.OrderBy` behavior on string comparison
我有以下代码
public class Model
{
public int Id { get; set; }
public string OrderNumber { get; set; }
}
class Program
{
static void Main(string[] args)
{
var models = new List<Model>
{
new Model {Id = 4, OrderNumber = "BT-3964-1"},
new Model {Id = 2, OrderNumber = "BT3924"},
new Model {Id = 1, OrderNumber = "bt3810v2"},
new Model {Id = 5, OrderNumber = "BILL-TEST100"},
new Model {Id = 3, OrderNumber = "BT-4887-Test3-Create"}
};
var reorderedModels = models.OrderBy(x => x.OrderNumber);
Console.WriteLine("The sorted models are:");
foreach (var model in reorderedModels)
{
Console.WriteLine($"OrderNumber: {model.OrderNumber}, Id: {model.Id}");
}
}
}
在 .NET Core 3.1 和 2.1 中,它给出以下输出
The sorted models are:
OrderNumber: BILL-TEST100, Id: 5
OrderNumber: bt3810v2, Id: 1
OrderNumber: BT3924, Id: 2
OrderNumber: BT-3964-1, Id: 4
OrderNumber: BT-4887-Test3-Create, Id: 3
但在 .NET 5.0 上,它给出以下输出
The sorted models are:
OrderNumber: BILL-TEST100, Id: 5
OrderNumber: BT-3964-1, Id: 4
OrderNumber: BT-4887-Test3-Create, Id: 3
OrderNumber: bt3810v2, Id: 1
OrderNumber: BT3924, Id: 2
为什么要进行重大更改?
补充说明:即使使用OrderBy(x => x.OrderNumber, StringComparer.InvariantCultureIgnoreCase)
,这个问题仍然存在
我猜这与默认使用 International Components for Unicode (ICU) 库有关。
您可以在此处具体阅读它,因为它会影响字符串比较:https://docs.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus
给出的示例是对字符串进行排序。他们的示例是关于实例化 SortedtSet<string>
,但可以扩展解决方案中的逻辑以涵盖您对 OrderBy
的使用,方法是提供您要使用的显式比较器。
例子:
//
// Potentially incorrect code - behavior might vary based on locale.
//
SortedSet<string> mySet = new SortedSet<string>();
List<string> list = GetListOfStrings();
list.Sort();
//
// Corrected code - uses ordinal sorting; doesn't vary by locale.
//
SortedSet<string> mySet = new SortedSet<string>(StringComparer.Ordinal);
List<string> list = GetListOfStrings();
list.Sort(StringComparer.Ordinal);
@Loggar 所说的以及对于您的特定情况,为了获得一致的行为,更改将是将字符串比较器传递给 OrderBy
:
.OrderBy(x => x, StringComparer.InvariantCultureIgnoreCase)
我有以下代码
public class Model
{
public int Id { get; set; }
public string OrderNumber { get; set; }
}
class Program
{
static void Main(string[] args)
{
var models = new List<Model>
{
new Model {Id = 4, OrderNumber = "BT-3964-1"},
new Model {Id = 2, OrderNumber = "BT3924"},
new Model {Id = 1, OrderNumber = "bt3810v2"},
new Model {Id = 5, OrderNumber = "BILL-TEST100"},
new Model {Id = 3, OrderNumber = "BT-4887-Test3-Create"}
};
var reorderedModels = models.OrderBy(x => x.OrderNumber);
Console.WriteLine("The sorted models are:");
foreach (var model in reorderedModels)
{
Console.WriteLine($"OrderNumber: {model.OrderNumber}, Id: {model.Id}");
}
}
}
在 .NET Core 3.1 和 2.1 中,它给出以下输出
The sorted models are:
OrderNumber: BILL-TEST100, Id: 5
OrderNumber: bt3810v2, Id: 1
OrderNumber: BT3924, Id: 2
OrderNumber: BT-3964-1, Id: 4
OrderNumber: BT-4887-Test3-Create, Id: 3
但在 .NET 5.0 上,它给出以下输出
The sorted models are:
OrderNumber: BILL-TEST100, Id: 5
OrderNumber: BT-3964-1, Id: 4
OrderNumber: BT-4887-Test3-Create, Id: 3
OrderNumber: bt3810v2, Id: 1
OrderNumber: BT3924, Id: 2
为什么要进行重大更改?
补充说明:即使使用OrderBy(x => x.OrderNumber, StringComparer.InvariantCultureIgnoreCase)
,这个问题仍然存在
我猜这与默认使用 International Components for Unicode (ICU) 库有关。
您可以在此处具体阅读它,因为它会影响字符串比较:https://docs.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus
给出的示例是对字符串进行排序。他们的示例是关于实例化 SortedtSet<string>
,但可以扩展解决方案中的逻辑以涵盖您对 OrderBy
的使用,方法是提供您要使用的显式比较器。
例子:
//
// Potentially incorrect code - behavior might vary based on locale.
//
SortedSet<string> mySet = new SortedSet<string>();
List<string> list = GetListOfStrings();
list.Sort();
//
// Corrected code - uses ordinal sorting; doesn't vary by locale.
//
SortedSet<string> mySet = new SortedSet<string>(StringComparer.Ordinal);
List<string> list = GetListOfStrings();
list.Sort(StringComparer.Ordinal);
@Loggar 所说的以及对于您的特定情况,为了获得一致的行为,更改将是将字符串比较器传递给 OrderBy
:
.OrderBy(x => x, StringComparer.InvariantCultureIgnoreCase)