分析linq源码OrderBy的实现原理

将OrderBy 所用到得源码copy在一个文件里,下面是测试console应用程序:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime;
using System.Collections;

namespace ConsoleApplication1
{
   
    internal struct Buffer<TElement>
    {
        internal int count;

        internal TElement[] items;
        /// <summary>
        ///  将可枚举的泛型变成数组形式
        /// </summary>
        /// <param name="source"></param>
        internal Buffer(IEnumerable<TElement> source)
        {
            TElement[] tElementArray = null;
            int count = 0;
            ICollection<TElement> tElements = source as ICollection<TElement>;
            if (tElements == null)
            {
                foreach (TElement tElement in source)
                {
                    if (tElementArray != null)
                    {
                        if ((int)tElementArray.Length == count)
                        {
                            TElement[] tElementArray1 = new TElement[count * 2];
                            Array.Copy(tElementArray, 0, tElementArray1, 0, count);
                            tElementArray = tElementArray1;
                        }
                    }
                    else
                    {
                        tElementArray = new TElement[4];
                    }
                    tElementArray[count] = tElement;
                    count++;
                }
            }
            else
            {
                count = tElements.Count;
                if (count > 0)
                {
                    tElementArray = new TElement[count];
                    tElements.CopyTo(tElementArray, 0);
                }
            }
            this.items = tElementArray;
            this.count = count;
        }

        internal TElement[] ToArray()
        {
            if (this.count != 0)
            {
                if ((int)this.items.Length != this.count)
                {
                    TElement[] tElementArray = new TElement[this.count];
                    Array.Copy(this.items, 0, tElementArray, 0, this.count);
                    return tElementArray;
                }
                else
                {
                    return this.items;
                }
            }
            else
            {
                return new TElement[0];
            }
        }
    }
    internal abstract class EnumerableSorter<TElement>
    {
        internal abstract void ComputeKeys(TElement[] elements, int count);

        internal abstract int CompareKeys(int index1, int index2);

        internal int[] Sort(TElement[] elements, int count)
        {
            ComputeKeys(elements, count);
            int[] map = new int[count];
            for (int i = 0; i < count; i++) map[i] = i;
            QuickSort(map, 0, count - 1);
            return map;
        }

        void QuickSort(int[] map, int left, int right)
        {
            do
            {
                int i = left;
                int j = right;
                int x = map[i + ((j - i) >> 1)];
                do
                {
                    while (i < map.Length && CompareKeys(x, map[i]) > 0) i++;
                    while (j >= 0 && CompareKeys(x, map[j]) < 0) j--;
                    if (i > j) break;
                    if (i < j)
                    {
                        int temp = map[i];
                        map[i] = map[j];
                        map[j] = temp;
                    }
                    i++;
                    j--;
                } while (i <= j);
                if (j - left <= right - i)
                {
                    if (left < j) QuickSort(map, left, j);
                    left = i;
                }
                else
                {
                    if (i < right) QuickSort(map, i, right);
                    right = j;
                }
            } while (left < right);
        }
    }
    internal class EnumerableSorter<TElement, TKey> : EnumerableSorter<TElement>
    {
        internal Func<TElement, TKey> keySelector;
        internal IComparer<TKey> comparer;
        internal bool descending;
        internal EnumerableSorter<TElement> next;
        internal TKey[] keys;

        internal EnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, EnumerableSorter<TElement> next)
        {
            this.keySelector = keySelector;
            this.comparer = comparer;
            this.descending = descending;
            this.next = next;
        }

        internal override void ComputeKeys(TElement[] elements, int count)
        {
            keys = new TKey[count];
            for (int i = 0; i < count; i++) keys[i] = keySelector(elements[i]);
            if (next != null) next.ComputeKeys(elements, count);
        }

        internal override int CompareKeys(int index1, int index2)
        {
            int c = comparer.Compare(keys[index1], keys[index2]);
            if (c == 0)
            {
                if (next == null) return index1 - index2;
                return next.CompareKeys(index1, index2);
            }
            return descending ? -c : c;
        }
    }
    internal abstract class OrderedEnumerable<TElement> : IOrderedEnumerable<TElement>
    {


        internal IEnumerable<TElement> source;

        public IEnumerator<TElement> GetEnumerator()
        {
            Buffer<TElement> buffer = new Buffer<TElement>(source);
            if (buffer.count > 0)
            {
                EnumerableSorter<TElement> sorter = GetEnumerableSorter(null);
                int[] map = sorter.Sort(buffer.items, buffer.count);
                sorter = null;
                for (int i = 0; i < buffer.count; i++) yield return buffer.items[map[i]];
            }
        }
        internal abstract EnumerableSorter<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next);

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        IOrderedEnumerable<TElement> IOrderedEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
        {
            OrderedEnumerable<TElement, TKey> result = new OrderedEnumerable<TElement, TKey>(source, keySelector, comparer, descending);
            result.parent = this;
            return result;
        }
    }

    internal class OrderedEnumerable<TElement, TKey> : OrderedEnumerable<TElement>
    {
        public OrderedEnumerable<TElement> parent;
        public Func<TElement, TKey> keySelector;
        public IComparer<TKey> comparer;
        public bool descending;

        internal OrderedEnumerable(IEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
        {
            if (source == null) throw new Exception("source");
            if (keySelector == null) throw new Exception("keySelector");
            this.source = source;
            this.parent = null;
            this.keySelector = keySelector;
            this.comparer = comparer != null ? comparer : Comparer<TKey>.Default;
            this.descending = descending;
        }

        internal override EnumerableSorter<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next)
        {
            EnumerableSorter<TElement> sorter = new EnumerableSorter<TElement, TKey>(keySelector, comparer, descending, next);
            if (parent != null) sorter = parent.GetEnumerableSorter(sorter);
            return sorter;
        }
    }


    public static class MyExtension
    {
        public static IOrderedEnumerable<TSource> OrderBySYM<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            return new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false);
        }
    }
    class Program
    {


        static void Main(string[] args)
        {

            string[] test = new string[] { "123", "456", "789", "187" };

            string[] testC = test.OrderBySYM(_ => int.Parse(_)).ToArray();
            var D = test.OrderBySYM(_ => int.Parse(_)).ToArray();
        }

    }
  
}

自己实现的OrderBySYM 和OrderBy 功能相同,发现使用的是快速排序,而且排序发生的地方:

internal override void ComputeKeys(TElement[] elements, int count)
{
keys = new TKey[count];
for (int i = 0; i < count; i++) keys[i] = keySelector(elements[i]);
if (next != null) next.ComputeKeys(elements, count);
}

转载于:https://www.cnblogs.com/symphony2010/archive/2012/08/02/2619795.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LINQ中,OrderBy是用来对集合进行升序排序的操作符。它可以通过指定排序的键来对集合中的元素进行排序。在T-SQL中,OrderBy操作符有严格的位置限制,而在LINQ中,OrderBy可以根据需要的顺序进行链式调用。引用给出了一个示例,该示例使用LINQ查询语法对数据库中的订单进行筛选和排序。其中,Where用于筛选出符合条件的订单,而OrderBy用于按照指定的属性进行排序。在LINQ中,OrderBy还可以和ThenBy连用,用于对多个属性进行排序。然而,在T-SQL中没有ThenBy的语句,所以需要使用多个OrderBy来实现。引用提供了一个示例,展示了如何使用多个OrderBy来对集合进行排序。需要注意的是,OrderBy操作不支持按type排序,也不支持匿名类。引用给出了一个示例,展示了在OrderBy操作中不能使用匿名类的限制。总之,LINQOrderBy操作可以用来对集合进行排序,并且可以根据需要进行链式调用和使用多个排序条件。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [LINQ to SQL语句(5)之Order By](https://blog.csdn.net/Johnson_hejun/article/details/3895356)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值