Core源码(六)Array.Sort
Sort方法
源码在位置在corefx\src\System.Runtime.Extensions\src\System\Collections\ArrayList.cs
corefx是.net 的源码库,直接在github搜索即可
// Sorts the elements in this list. Uses Array.Sort with the // provided comparer. public virtual void Sort(IComparer comparer) { Sort(0, Count, comparer); }
这里会根据IComparer类型进行排序,如果不传入会使用默认值
IComparer
[NullableContextAttribute(2)] public interface IComparer { // // 摘要: // Compares two objects and returns a value indicating whether one is less than, // equal to, or greater than the other. // // 参数: // x: // The first object to compare. // // y: // The second object to compare. // // 返回结果: // A signed integer that indicates the relative values of x and y: - If less than // 0, x is less than y. - If 0, x equals y. - If greater than 0, x is greater than // y. . // // 异常: // T:System.ArgumentException: // Neither x nor y implements the System.IComparable interface. -or- x and y are // of different types and neither one can handle comparisons with the other. int Compare(object? x, object? y); }
Comparer默认实现
[Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class Comparer : IComparer, ISerializable { private CompareInfo _compareInfo; public static readonly Comparer Default = new Comparer(CultureInfo.CurrentCulture); public static readonly Comparer DefaultInvariant = new Comparer(CultureInfo.InvariantCulture); // Compares two Objects by calling CompareTo. // If a == b, 0 is returned. // If a implements IComparable, a.CompareTo(b) is returned. // If a doesn't implement IComparable and b does, -(b.CompareTo(a)) is returned. // Otherwise an exception is thrown. // public int Compare(Object a, Object b) { if (a == b) return 0; if (a == null) return -1; if (b == null) return 1; string sa = a as string; string sb = b as string; //都不为空的情况,直接调用Compare if (sa != null && sb != null) return _compareInfo.Compare(sa, sb); IComparable ia = a as IComparable; if (ia != null) return ia.CompareTo(b); IComparable ib = b as IComparable; if (ib != null) return -ib.CompareTo(a); throw new ArgumentException(SR.Argument_ImplementIComparable); } }
CompareInfo
对比的核心方法
[Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class CompareInfo : IDeserializationCallback public virtual int Compare(string string1, string string2) { return (Compare(string1, string2, CompareOptions.None)); } public virtual int Compare(string string1, string string2, CompareOptions options) { //Our paradigm is that null sorts less than any other string and //that two nulls sort as equal. if (string1 == null) { if (string2 == null) { return (0); // Equal } return (-1); // null < non-null } if (string2 == null) { return (1); // non-null > null } if (_invariantMode) { if ((options & CompareOptions.IgnoreCase) != 0) return CompareOrdinalIgnoreCase(string1, string2); return String.CompareOrdinal(string1, string2); } return CompareString(string1.AsSpan(), string2.AsSpan(), options); }
CompareOrdinal方法是实际进行字符串对比的,位于framework程序集中。
#region 程序集 mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
// C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\mscorlib.dll
#endregion
这里我下载了4.5的源码,位于如下位置
C:\project\SourceCode\1 net framework\Source\NDP\clr\src\BCL\System
// Compares strA and strB using an ordinal (code-point) comparison. // [Pure] public static int CompareOrdinal(String strA, String strB) { // Most common case, first character is different. if ((strA.m_firstChar - strB.m_firstChar) != 0) { return strA.m_firstChar - strB.m_firstChar; } //首字母相同的情况下,金星整个字符串的对比 return CompareOrdinalHelper(strA, strB); }
自己定义IComparer
class Program
{
static void Main()
{
Employee [] employees = new Employee[4];
for (int i = 0; i < 4; i++)
{
employees[i] = new Employee();
}
employees[0].Age = 12;
employees[1].Age = 34;
employees[2].Age = 64;
employees[3].Age = 53;
Array.Sort(employees, new EmployeeSortAdapter());
foreach (Employee emp in employees)
{
Console.WriteLine(emp.Age);
}
Console.Read();
}
}
public class Employee
{
public int Age { get; set; }
}
class EmployeeSortAdapter :IComparer<Employee>
{
public int Compare(Employee emp1, Employee emp2)
{
if (emp1==null&&emp2==null)
{
return 0;
}
if (emp1==null)
{
return -1;
}
if (emp2==null)
{
return 1;
}
if (emp1.Age > emp2.Age)
{
return 1;
}
else if (emp1.Age < emp2.Age)
{
return -1;
}
return 0;
}
}