C# 如何检查列表是否已排序?

C# 如何检查列表是否已排序?,c#,unit-testing,list,html-lists,C#,Unit Testing,List,Html Lists,我正在做一些单元测试,我想知道是否有任何方法可以测试一个列表是否按照它包含的对象的属性排序 现在我这样做,但我不喜欢,我想要一个更好的方式。谁能帮帮我吗 // (fill the list) List<StudyFeedItem> studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20); StudyFeedItem previous = studyFeeds.First();

我正在做一些单元测试,我想知道是否有任何方法可以测试一个列表是否按照它包含的对象的属性排序

现在我这样做,但我不喜欢,我想要一个更好的方式。谁能帮帮我吗

// (fill the list)
List<StudyFeedItem> studyFeeds = 
    Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);   

StudyFeedItem previous = studyFeeds.First();

foreach (StudyFeedItem item in studyFeeds)
{
    if (item != previous)
    {
        Assert.IsTrue(previous.Date > item.Date);
    }

    previous = item;
}
那么:

var list = items.ToList();
for(int i = 1; i < list.Count; i++) {
    Assert.IsTrue(yourComparer.Compare(list[i - 1], list[i]) <= 0);
} 
其中,比较器是比较器的一个实例,它实现了。这可确保每个元素都小于枚举中的下一个元素。

如何:

var list = items.ToList();
for(int i = 1; i < list.Count; i++) {
    Assert.IsTrue(yourComparer.Compare(list[i - 1], list[i]) <= 0);
} 

其中,比较器是比较器的一个实例,它实现了。这可以确保每个元素都少于枚举中的下一个元素。

LINQ-y使用单独的排序查询可能会有些问题

var sorted = from item in items
 orderby item.Priority
 select item;

Assert.IsTrue(items.SequenceEquals(sorted));
类型推断意味着您需要一个

 where T : IHasPriority

但是,如果您有多个具有相同优先级的项,那么对于单元测试断言,您最好按照Jason的建议使用列表索引进行循环。

LINQ-y应该使用单独的排序查询

var sorted = from item in items
 orderby item.Priority
 select item;

Assert.IsTrue(items.SequenceEquals(sorted));
类型推断意味着您需要一个

 where T : IHasPriority

但是,如果您有多个具有相同优先级的项,那么对于单元测试断言,您最好按照Jason的建议使用列表索引进行循环。

无论如何,您必须遍历列表,并确保这些项按您想要的顺序排列。由于项目比较是自定义的,因此您可以考虑为此创建一个通用方法并传入一个比较函数,这与列表排序使用比较函数的方式相同。

您必须以这样或那样的方式遍历列表,并确保项目按您想要的顺序排列。由于项目比较是自定义的,因此您可以考虑为此创建一个通用方法,并传入一个比较函数,这与列表排序使用比较函数的方式相同

var studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);
var orderedFeeds = studyFeeds.OrderBy(f => f.Date);

for (int i = 0; i < studyFeeds.Count; i++)
{
    Assert.AreEqual(orderedFeeds[i].Date, studyFeeds[i].Date);
}
因为他还没死呢


因为他还没死呢

如果您的单元测试框架有助手方法来断言集合的相等性,那么您应该能够执行如下NUnit风格的操作:

var sorted = studyFeeds.OrderBy(s => s.Date);
CollectionAssert.AreEqual(sorted.ToList(), studyFeeds.ToList());

assert方法可用于任何IEnumerable,但当两个集合都是IList类型或某事物的数组时,assert失败时抛出的错误消息将包含第一个不合适元素的索引。

如果单元测试框架具有断言集合相等性的帮助器方法,你应该可以做一些类似于努尼特风味的事情:

var sorted = studyFeeds.OrderBy(s => s.Date);
CollectionAssert.AreEqual(sorted.ToList(), studyFeeds.ToList());

assert方法可用于任何IEnumerable,但当两个集合都是IList类型或某物数组时,assert失败时抛出的错误消息将包含第一个不合适元素的索引。

如果您使用的是MSTest,您可能需要看一看

可能是在断言中使用的另一个有用的API

在这两种情况下,您都应该准备一个按预期顺序保存预期列表的列表,然后将该列表与结果进行比较

下面是一个例子:

var studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);   
var expectedList = studyFeeds.OrderByDescending(x => x.Date);
Assert.IsTrue(expectedList.SequenceEqual(studyFeeds));

如果您正在使用MSTest,您可能需要查看

可能是在断言中使用的另一个有用的API

在这两种情况下,您都应该准备一个按预期顺序保存预期列表的列表,然后将该列表与结果进行比较

下面是一个例子:

var studyFeeds = Feeds.GetStudyFeeds(2120, DateTime.Today.AddDays(-200), 20);   
var expectedList = studyFeeds.OrderByDescending(x => x.Date);
Assert.IsTrue(expectedList.SequenceEqual(studyFeeds));

NET 4.0的一种方法是使用该方法压缩列表,使其自身偏移1,从而将列表中的每个项目与后续项目配对。然后,您可以检查每对的条件是否为真,例如

var ordered = studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => new { a, b })
                        .All(p => p.a.Date < p.b.Date);
如果您使用的是早期版本的框架,那么您可以编写自己的Zip方法,而不会有太多麻烦,下面的参数验证和枚举数的处理(如果适用)将留给读者:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    Func<TFirst, TSecond, TResult> selector)
{
    var e1 = first.GetEnumerator();
    var e2 = second.GetEnumerator();
    while (e1.MoveNext() & e2.MoveNext()) // one & is important
        yield return selector(e1.Current, e2.Current);
}

NET 4.0的一种方法是使用该方法压缩列表,使其自身偏移1,从而将列表中的每个项目与后续项目配对。然后,您可以检查每对的条件是否为真,例如

var ordered = studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => new { a, b })
                        .All(p => p.a.Date < p.b.Date);
如果您使用的是早期版本的框架,那么您可以编写自己的Zip方法,而不会有太多麻烦,下面的参数验证和枚举数的处理(如果适用)将留给读者:

public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(
    this IEnumerable<TFirst> first,
    IEnumerable<TSecond> second,
    Func<TFirst, TSecond, TResult> selector)
{
    var e1 = first.GetEnumerator();
    var e2 = second.GetEnumerator();
    while (e1.MoveNext() & e2.MoveNext()) // one & is important
        yield return selector(e1.Current, e2.Current);
}

下面是我如何使用Linq和I Compariable实现它的,它可能不是最好的,但对我来说是可行的,并且它独立于测试框架

所以这个电话是这样的:

    myList.IsOrderedBy(a => a.StartDate)
public static System.ComponentModel.ListSortDirection? SortDirection<T>(this IEnumerable<T> items, Comparer<T> comparer = null)
{
    if (items == null) throw new ArgumentNullException("items");
    if (comparer == null) comparer = Comparer<T>.Default;

    bool ascendingOrder = true; bool descendingOrder = true;
    using (var e = items.GetEnumerator())
    {
        if (e.MoveNext())
        {
            T last = e.Current; // first item
            while (e.MoveNext())
            {
                int diff = comparer.Compare(last, e.Current);
                if (diff > 0)
                    ascendingOrder = false;
                else if (diff < 0)
                    descendingOrder = false;

                if (!ascendingOrder && !descendingOrder)
                    break;
                last = e.Current;
            }
        }
    }
    if (ascendingOrder)
        return System.ComponentModel.ListSortDirection.Ascending;
    else if (descendingOrder)
        return System.ComponentModel.ListSortDirection.Descending;
    else
        return null;
}
这适用于实现IComparable的任何内容,因此数字字符串和从IComparable继承的任何内容:

    public static bool IsOrderedBy<T, TProperty>(this List<T> list, Expression<Func<T, TProperty>> propertyExpression) where TProperty : IComparable<TProperty>
    {
        var member = (MemberExpression) propertyExpression.Body;
        var propertyInfo = (PropertyInfo) member.Member;
        IComparable<TProperty> previousValue = null;
        for (int i = 0; i < list.Count(); i++)
        {
            var currentValue = (TProperty)propertyInfo.GetValue(list[i], null);
            if (previousValue == null)
            {
                previousValue = currentValue;
                continue;
            }

            if(previousValue.CompareTo(currentValue) > 0) return false;
            previousValue = currentValue;

        }

        return true;
    }

希望这对我有所帮助,我花了很多时间才完成这项工作。

以下是我如何使用Linq和I Compariable完成这项工作的,它可能不是最好的,但对我来说是可行的,而且它与测试框架无关

所以这个电话是这样的:

    myList.IsOrderedBy(a => a.StartDate)
public static System.ComponentModel.ListSortDirection? SortDirection<T>(this IEnumerable<T> items, Comparer<T> comparer = null)
{
    if (items == null) throw new ArgumentNullException("items");
    if (comparer == null) comparer = Comparer<T>.Default;

    bool ascendingOrder = true; bool descendingOrder = true;
    using (var e = items.GetEnumerator())
    {
        if (e.MoveNext())
        {
            T last = e.Current; // first item
            while (e.MoveNext())
            {
                int diff = comparer.Compare(last, e.Current);
                if (diff > 0)
                    ascendingOrder = false;
                else if (diff < 0)
                    descendingOrder = false;

                if (!ascendingOrder && !descendingOrder)
                    break;
                last = e.Current;
            }
        }
    }
    if (ascendingOrder)
        return System.ComponentModel.ListSortDirection.Ascending;
    else if (descendingOrder)
        return System.ComponentModel.ListSortDirection.Descending;
    else
        return null;
}
这适用于实现IComparable的任何内容,因此数字字符串和从IComparable继承的任何内容:

    public static bool IsOrderedBy<T, TProperty>(this List<T> list, Expression<Func<T, TProperty>> propertyExpression) where TProperty : IComparable<TProperty>
    {
        var member = (MemberExpression) propertyExpression.Body;
        var propertyInfo = (PropertyInfo) member.Member;
        IComparable<TProperty> previousValue = null;
        for (int i = 0; i < list.Count(); i++)
        {
            var currentValue = (TProperty)propertyInfo.GetValue(list[i], null);
            if (previousValue == null)
            {
                previousValue = currentValue;
                continue;
            }

            if(previousValue.CompareTo(currentValue) > 0) return false;
            previousValue = currentValue;

        }

        return true;
    }
希望这能有所帮助,我花了很长时间才完成这项工作。

Nunit 2.5介绍了一种很好的语法,用于验证集合的顺序:

Assert.That(collection, Is.Ordered.By("PropertyName"));
无需手动订购和比较。

Nunit 2.5的推出和一个不错的 用于验证集合顺序的语法:

Assert.That(collection, Is.Ordered.By("PropertyName"));

不需要手动排序和比较。

这样的东西,不需要对列表进行排序,怎么样

    public static bool IsAscendingOrder<T>(this IEnumerable<T> seq) where T : IComparable
    {
        var seqArray = seq as T[] ?? seq.ToArray();
        return !seqArray.Where((e, i) =>
            i < seqArray.Count() - 1 &&
            e.CompareTo(seqArray.ElementAt(i + 1)) >= 0).Any();
    }

像这样的东西呢,不排序列表

    public static bool IsAscendingOrder<T>(this IEnumerable<T> seq) where T : IComparable
    {
        var seqArray = seq as T[] ?? seq.ToArray();
        return !seqArray.Where((e, i) =>
            i < seqArray.Count() - 1 &&
            e.CompareTo(seqArray.ElementAt(i + 1)) >= 0).Any();
    }
Greg Beech虽然非常优秀,但可以通过在Zip中执行测试来进一步简化。因此,不是:

var ordered = studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => new { a, b })
                        .All(p => p.a.Date <= p.b.Date);
您可以简单地执行以下操作:

var ordered = !studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => a.Date <= b.Date)
                        .Contains(false);
这将为您保存一个lambda表达式和一个匿名类型

在我看来,删除匿名类型也使其更易于阅读。

Greg Beech虽然非常优秀,但可以通过在Zip本身中执行测试来进一步简化。因此,不是:

var ordered = studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => new { a, b })
                        .All(p => p.a.Date <= p.b.Date);
double[] score3 = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 };
double[] score4 = new double[] { 2.2, 4.5, 5, 12.2, 13.3, 17.2 };

bool isordered3 = score3.Aggregate((double?)double.MinValue,(accum,elem)=>(elem>(accum??(double?)double.MaxValue).Value)?(double?)elem:(double?)null) !=null;
bool isordered4 = score4.Aggregate((double?)double.MinValue,(accum,elem)=>(elem>(accum??(double?)double.MaxValue).Value)?(double?)elem:(double?)null) !=null;

Console.WriteLine ("isordered3 {0}",isordered3);
Console.WriteLine ("isordered4 {0}",isordered4);
您可以简单地执行以下操作:

var ordered = !studyFeeds.Zip(studyFeeds.Skip(1), (a, b) => a.Date <= b.Date)
                        .Contains(false);
这将为您保存一个lambda表达式和一个匿名类型


在我看来,删除匿名类型也使其更易于阅读。

这里有一个更轻量级的通用版本。要测试降序,请将>=0比较更改为,这是一个更轻量级的通用版本。为了测试降序,将>=0的比较改为,而AnorZaken和Greg Beech的答案非常好,因为他们不需要使用扩展方法,所以有时最好避免使用Zip,因为用这种方式枚举某些可枚举项可能会很昂贵

double[] score3 = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 };
double[] score4 = new double[] { 2.2, 4.5, 5, 12.2, 13.3, 17.2 };

bool isordered3 = score3.Aggregate((double?)double.MinValue,(accum,elem)=>(elem>(accum??(double?)double.MaxValue).Value)?(double?)elem:(double?)null) !=null;
bool isordered4 = score4.Aggregate((double?)double.MinValue,(accum,elem)=>(elem>(accum??(double?)double.MaxValue).Value)?(double?)elem:(double?)null) !=null;

Console.WriteLine ("isordered3 {0}",isordered3);
Console.WriteLine ("isordered4 {0}",isordered4);
可以在聚合中找到解决方案

double[] score1 = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 };
double[] score2 = new double[] { 2.2, 4.5, 5, 12.2, 13.3, 17.2 };

bool isordered1 = score1.Aggregate(double.MinValue,(accum,elem)=>elem>=accum?elem:double.MaxValue) < double.MaxValue;
bool isordered2 = score2.Aggregate(double.MinValue,(accum,elem)=>elem>=accum?elem:double.MaxValue) < double.MaxValue;

Console.WriteLine ("isordered1 {0}",isordered1);
Console.WriteLine ("isordered2 {0}",isordered2);

虽然AnorZaken和Greg Beech的答案很好,因为他们不需要使用扩展方法,但有时避免使用Zip是很好的,因为用这种方式枚举某些可枚举项可能会很昂贵

可以在聚合中找到解决方案

double[] score1 = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 };
double[] score2 = new double[] { 2.2, 4.5, 5, 12.2, 13.3, 17.2 };

bool isordered1 = score1.Aggregate(double.MinValue,(accum,elem)=>elem>=accum?elem:double.MaxValue) < double.MaxValue;
bool isordered2 = score2.Aggregate(double.MinValue,(accum,elem)=>elem>=accum?elem:double.MaxValue) < double.MaxValue;

Console.WriteLine ("isordered1 {0}",isordered1);
Console.WriteLine ("isordered2 {0}",isordered2);
基于Linq的答案是:

您可以使用SequenceEqual方法检查原始的和已订购的是否相同

var isOrderedAscending = lJobsList.SequenceEqual(lJobsList.OrderBy(x => x));
var isOrderedDescending = lJobsList.SequenceEqual(lJobsList.OrderByDescending(x => x));
别忘了导入System.Linq命名空间

此外:

我重申这个答案是基于Linq的,您可以通过创建自定义扩展方法来实现更高的效率

另外,如果有人仍然想使用Linq并检查序列是否都是按升序或降序排列的,那么您可以获得更高的效率,如下所示:

var orderedSequence = lJobsList.OrderBy(x => x)
                               .ToList();

var reversedOrderSequence = orderedSequence.AsEnumerable()
                                           .Reverse();

if (lJobsList.SequenceEqual(orderedSequence))
{
     // Ordered in ascending
}
else (lJobsList.SequenceEqual(reversedOrderSequence))
{
     // Ordered in descending
}
基于Linq的答案是:

您可以使用SequenceEqual方法检查原始的和已订购的是否相同

var isOrderedAscending = lJobsList.SequenceEqual(lJobsList.OrderBy(x => x));
var isOrderedDescending = lJobsList.SequenceEqual(lJobsList.OrderByDescending(x => x));
别忘了导入System.Linq命名空间

此外:

我重申这个答案是基于Linq的,您可以通过创建自定义扩展方法来实现更高的效率

另外,如果有人仍然想使用Linq并检查序列是否都是按升序或降序排列的,那么您可以获得更高的效率,如下所示:

var orderedSequence = lJobsList.OrderBy(x => x)
                               .ToList();

var reversedOrderSequence = orderedSequence.AsEnumerable()
                                           .Reverse();

if (lJobsList.SequenceEqual(orderedSequence))
{
     // Ordered in ascending
}
else (lJobsList.SequenceEqual(reversedOrderSequence))
{
     // Ordered in descending
}

您可以先创建列表的有序版本和无序版本:

var asc = jobs.OrderBy(x => x);
var desc = jobs.OrderByDescending(x => x);
现在将原始列表与以下两个列表进行比较:

if (jobs.SequenceEqual(asc) || jobs.SequenceEquals(desc)) // ...

您可以先创建列表的有序版本和无序版本:

var asc = jobs.OrderBy(x => x);
var desc = jobs.OrderByDescending(x => x);
现在将原始列表与以下两个列表进行比较:

if (jobs.SequenceEqual(asc) || jobs.SequenceEquals(desc)) // ...

发布的涉及列表排序的解决方案成本很高——确定列表是否已排序可以在ON中完成。下面是一个扩展方法,它将检查:

public static bool IsOrdered<T>(this IList<T> list, IComparer<T> comparer = null)
{
    if (comparer == null)
    {
        comparer = Comparer<T>.Default;
    }

    if (list.Count > 1)
    {
        for (int i = 1; i < list.Count; i++)
        {
            if (comparer.Compare(list[i - 1], list[i]) > 0)
            {
                return false;
            }
        }
    }
    return true;
}

通过将>0更改为<0,可以轻松实现相应的ISORDEDESCENDING。

发布的涉及列表排序的解决方案非常昂贵-确定列表是否已排序可以在ON中完成。下面是一个扩展方法,它将检查:

public static bool IsOrdered<T>(this IList<T> list, IComparer<T> comparer = null)
{
    if (comparer == null)
    {
        comparer = Comparer<T>.Default;
    }

    if (list.Count > 1)
    {
        for (int i = 1; i < list.Count; i++)
        {
            if (comparer.Compare(list[i - 1], list[i]) > 0)
            {
                return false;
            }
        }
    }
    return true;
}

通过将>0更改为<0,可以轻松实现相应的IsOrderedDescending。

您可以使用如下扩展方法:

    myList.IsOrderedBy(a => a.StartDate)
public static System.ComponentModel.ListSortDirection? SortDirection<T>(this IEnumerable<T> items, Comparer<T> comparer = null)
{
    if (items == null) throw new ArgumentNullException("items");
    if (comparer == null) comparer = Comparer<T>.Default;

    bool ascendingOrder = true; bool descendingOrder = true;
    using (var e = items.GetEnumerator())
    {
        if (e.MoveNext())
        {
            T last = e.Current; // first item
            while (e.MoveNext())
            {
                int diff = comparer.Compare(last, e.Current);
                if (diff > 0)
                    ascendingOrder = false;
                else if (diff < 0)
                    descendingOrder = false;

                if (!ascendingOrder && !descendingOrder)
                    break;
                last = e.Current;
            }
        }
    }
    if (ascendingOrder)
        return System.ComponentModel.ListSortDirection.Ascending;
    else if (descendingOrder)
        return System.ComponentModel.ListSortDirection.Descending;
    else
        return null;
}

您可以使用如下扩展方法:

    myList.IsOrderedBy(a => a.StartDate)
public static System.ComponentModel.ListSortDirection? SortDirection<T>(this IEnumerable<T> items, Comparer<T> comparer = null)
{
    if (items == null) throw new ArgumentNullException("items");
    if (comparer == null) comparer = Comparer<T>.Default;

    bool ascendingOrder = true; bool descendingOrder = true;
    using (var e = items.GetEnumerator())
    {
        if (e.MoveNext())
        {
            T last = e.Current; // first item
            while (e.MoveNext())
            {
                int diff = comparer.Compare(last, e.Current);
                if (diff > 0)
                    ascendingOrder = false;
                else if (diff < 0)
                    descendingOrder = false;

                if (!ascendingOrder && !descendingOrder)
                    break;
                last = e.Current;
            }
        }
    }
    if (ascendingOrder)
        return System.ComponentModel.ListSortDirection.Ascending;
    else if (descendingOrder)
        return System.ComponentModel.ListSortDirection.Descending;
    else
        return null;
}

检查序列可能有四种不同的结果。“相同”表示序列中的所有元素相同或序列为空:

enum Sort {
  Unsorted,
  Same,
  SortedAscending,
  SortedDescending
}
以下是检查序列排序的方法:

Sort GetSort<T>(IEnumerable<T> source, IComparer<T> comparer = null) {
  if (source == null)
    throw new ArgumentNullException(nameof(source));
  if (comparer == null)
    comparer = Comparer<T>.Default;

  using (var enumerator = source.GetEnumerator()) {
    if (!enumerator.MoveNext())
      return Sort.Same;
    Sort? result = null;
    var previousItem = enumerator.Current;
    while (enumerator.MoveNext()) {
      var nextItem = enumerator.Current;
      var comparison = comparer.Compare(previousItem, nextItem);
      if (comparison < 0) {
        if (result == Sort.SortedDescending)
          return Sort.Unsorted;
        result = Sort.SortedAscending;
      }
      else if (comparison > 0) {
        if (result == Sort.SortedAscending)
          return Sort.Unsorted;
        result = Sort.SortedDescending;
      }
    }
    return result ?? Sort.Same;
  }
}

我直接使用枚举数而不是foreach循环,因为我需要成对检查序列的元素。它使代码更加复杂,但效率也更高。

检查序列可能有四种不同的结果。“相同”表示序列中的所有元素相同或序列为空:

enum Sort {
  Unsorted,
  Same,
  SortedAscending,
  SortedDescending
}
以下是检查序列排序的方法:

Sort GetSort<T>(IEnumerable<T> source, IComparer<T> comparer = null) {
  if (source == null)
    throw new ArgumentNullException(nameof(source));
  if (comparer == null)
    comparer = Comparer<T>.Default;

  using (var enumerator = source.GetEnumerator()) {
    if (!enumerator.MoveNext())
      return Sort.Same;
    Sort? result = null;
    var previousItem = enumerator.Current;
    while (enumerator.MoveNext()) {
      var nextItem = enumerator.Current;
      var comparison = comparer.Compare(previousItem, nextItem);
      if (comparison < 0) {
        if (result == Sort.SortedDescending)
          return Sort.Unsorted;
        result = Sort.SortedAscending;
      }
      else if (comparison > 0) {
        if (result == Sort.SortedAscending)
          return Sort.Unsorted;
        result = Sort.SortedDescending;
      }
    }
    return result ?? Sort.Same;
  }
}

我直接使用枚举数而不是foreach循环,因为我需要成对检查序列的元素。它使代码更复杂,但也更高效。

您可以在扩展中使用lambda:

public static bool IsAscending<T>(this IEnumerable<T> self, Func<T, T, int> compareTo) {
  var list = self as IList<T> ?? self.ToList();
  if (list.Count < 2) {
    return true;
  }
  T a = list[0];
  for (int i = 1; i < list.Count; i++) {
    T b = list[i];
    if (compareTo(a, b) > 0) {
      return false;
    }
    a = b;
  }
  return true;
}
更多:


您可以在扩展中使用lambda:

public static bool IsAscending<T>(this IEnumerable<T> self, Func<T, T, int> compareTo) {
  var list = self as IList<T> ?? self.ToList();
  if (list.Count < 2) {
    return true;
  }
  T a = list[0];
  for (int i = 1; i < list.Count; i++) {
    T b = list[i];
    if (compareTo(a, b) > 0) {
      return false;
    }
    a = b;
  }
  return true;
}
更多:


注意不要测试不需要测试的东西。您是确保查询包含预期的ORDERBY子句,还是只是检查ORDERBY子句是否有效?后者是浪费。@Chris-这是一个很好的观点+1,当我问这个问题时,我也在想同样的事情。为什么你会说测试订单是浪费?那么,我是否应该简单地信任DB引擎和CLR来保持事情的正常进行?@PITADev:是的,你应该绝对信任DB引擎和CLR来保持事情的正常进行。你不是在测试int x=2,y=2,z=x+y是否有Assert.IsTruez==4'成功吗?


您应该对公共方法的行为进行单元测试,仅此而已。因此,如果repository.GetItemstrue的预期行为返回一个有序的项目列表,那么测试它。但是不要测试items.OrderByx=>x,新的YourComparer确实会对列表进行排序。但是,请进行单元测试,确保您的比较器确实能够正确比较。l.OrderBye=>e.SequenceEqual是最简单的方法LINQ@Dennis我不知道为什么这很重要。这里和那里的答案都显示了Linq和for-loop方法:注意不要测试不需要测试的东西。您是确保查询包含预期的ORDERBY子句,还是只是检查ORDERBY子句是否有效?后者是浪费。@Chris-这是一个很好的观点+1,当我问这个问题时,我也在想同样的事情。为什么你会说测试订单是浪费?那么,我是否应该简单地信任DB引擎和CLR来保持事情的正常进行?@PITADev:是的,你应该绝对信任DB引擎和CLR来保持事情的正常进行。你不是在测试int x=2,y=2,z=x+y是否有Assert.IsTruez==4'成功吗?您应该对公共方法的行为进行单元测试,仅此而已。因此,如果repository.GetItemstrue的预期行为返回一个有序的项目列表,那么测试它。但是不要测试items.OrderByx=>x,新的YourComparer确实会对列表进行排序。但是,请进行单元测试,确保您的比较器确实能够正确比较。l.OrderBye=>e.SequenceEqual是最简单的方法LINQ@Dennis我不知道为什么这很重要。这里和那里的答案都显示了Linq和for-loop方法:+1.美好的我使用NUnit很多年了,不知道这件事。还发现了FileAssert和StringAssert!谢谢。它不工作:。错误消息:Baischana.Components.Services.Test.StudyFeedsTest.GetStudyFeeds_IsordedByDate:应为:但was:<,>就计算复杂性而言,对列表排序非常无效。+1对于CollectionAssert,我不知道这一点@el pescado:没错,但这是一个单元测试,而不是生产代码…@Nicole:这是断言失败时收到的错误消息。尝试将两个IList类型的对象传递给assert方法。我的答案被编辑以执行此操作,它应该会给您另一条错误消息,其中包含第一个不合适元素的索引。+1。美好的我使用NUnit很多年了,不知道这件事。还发现了FileAssert和StringAssert!谢谢。它不工作:。错误消息:Baischana.Components.Services.Test.StudyFeedsTest.GetStudyFeeds_IsordedByDate:应为:但was:<,>就计算复杂性而言,对列表排序非常无效。+1对于CollectionAssert,我不知道这一点@el pescado:没错,但这是一个单元测试,而不是生产代码…@Nicole:这是断言失败时收到的错误消息。尝试将两个IList类型的对象传递给assert方法我的答案被编辑以执行此操作,它会给您另一条错误消息,包含第一个不合适元素的索引。FYI:merged from FYI:merged from FYI:merged from FYI:merged from FYI:merged from This将比使用OrderBy的其他答案具有更高的内存效率。这需要放在最上面。这可以进一步简化,因此它只使用一个lambda表达式,而不是两个,并摆脱匿名类型,提高可读性..:需要解决的一个问题是,这将比使用OrderBy的其他答案更节省内存。这需要放在最上面。这可以进一步简化,因此它只使用一个lambda表达式而不是两个,并摆脱匿名类型,提高可读性值得修复的一件事是我应该这样做的条件,但在它的当前状态下非常有限,无法在设置acending/descending时按多列排序:我喜欢这样,但在它的当前状态是非常有限的,不能按多个列排序,同时设置排序/降序:你能解释一下你的代码在做什么吗?只发布代码作为答案不是最好的做法。你能解释一下你的代码在做什么吗?仅将代码作为答案发布不是最佳做法。>=是错误的,它将在[1,1,1,2,3]上返回false。修改此项以检测反向排序也很简单。这比对数据进行排序的方法要好得多,这会让我感到厌烦。你不能使用>或任何运算符来比较泛型方法中的元素。可与IList一起使用,但不能与IList甚至IEnumerable一起使用。事实上,我应该在VS中编写,而不是在浏览器中编写!使用您使用的相同比较器方法更新。>=错误,它将在[1,1,1,2,3]上返回false。修改此方法以检测反向排序也很简单。这比对数据进行排序的方法要好得多,这会让我感到厌烦。您不能使用>或任何运算符来比较泛型方法中的元素。可用于IList,但不适用于IList,甚至不适用于IEnumerable。事实上,我应该写这篇文章

在VS中而不是在浏览器中!使用与您使用的相同的比较器方法进行了更新。这对输入的迭代次数比我预期的自包含LINQ函数要多得多。@Rawling:因为Any和First。它不迭代序列,只检查第一个序列。如果任何项没有排序,它将停止枚举并返回false。它仍然调用GetEnumerable。如果这很贵,而且可能很贵,那么你的要求是你需要的三倍以上。@Rawling:是的,公认的答案更优雅。但是OrderBy+SequenceEqual不是效率较低吗?因为它需要先对整个序列排序,然后才能开始使用SequenceEqual,而我的foreach可以立即比较顺序?它还需要处理两次以检查两个方向,而我的循环只需要一个方向。@TimSchmelter您的答案比公认的答案要好。但是我个人会使用隐式枚举器,使用var e=items.GetEnumerator和e.MoveNext和e.Current来避免任何“Skip and First”。这比我期望的自包含LINQ函数迭代输入的次数多得多。@Rawling:因为Any and First。它不迭代序列,只检查第一个序列。如果任何项没有排序,它将停止枚举并返回false。它仍然调用GetEnumerable。如果这很贵,而且可能很贵,那么你的要求是你需要的三倍以上。@Rawling:是的,公认的答案更优雅。但是OrderBy+SequenceEqual不是效率较低吗?因为它需要先对整个序列排序,然后才能开始使用SequenceEqual,而我的foreach可以立即比较顺序?它还需要处理两次以检查两个方向,而我的循环只需要一个方向。@TimSchmelter您的答案比公认的答案要好。但我个人会使用带有e.MoveNext和e.Current的var e=items.GetEnumerator的隐式枚举器,以避免任何“跳过”和“第一个”。@PavelZagalsky很乐意提供帮助。但别忘了还有其他更有效的方法,必须由你自己来实施。@Downvoter你能解释一下downvoting的原因吗?有时我不理解人们:@PavelZagalsky:有些人只能伤害,他们没有能力治疗。我重复一遍,Linq和扩展方法与性能无关。@PavelZagalsky很乐意提供帮助。但别忘了还有其他更有效的方法,必须由你自己来实施。@Downvoter你能解释一下downvoting的原因吗?有时我不理解人们:@PavelZagalsky:有些人只能伤害,他们没有能力治疗。我重复一遍,Linq和扩展方法与性能无关。问题是:是否有任何方法可以测试列表是否按其包含的对象的属性排序。因此:如果序列按给定属性排序,则返回true的测试。否:如果序列等于另一个序列。我会选择一种扩展方法,可能使用Enumerable.Aggregate。问题是:是否有任何方法可以测试列表是否按其包含的对象的属性排序。因此:如果序列按给定属性排序,则返回true的测试。否:如果序列等于另一个序列。我会选择一个扩展方法,可能使用Enumerable.Aggregate。我发现这个版本更容易阅读:studyFeeds.ZipstudyFeeds.Skip1,a,b=>a.Datetrue;就我个人而言,我不能说我感觉到所有测试都是正确的与任何测试都是错误的之间有任何清晰的区别,额外的lambda对我来说似乎是不必要的,但我猜无论什么东西会让你的船漂浮。@StackHola我想你有一个拼写错误:b=>true总是返回true忽略b是假还是真,我想你的意思是b=>b@SteveCadwallader是的,你是对的,不能重新编辑。正确的形式是:studyFeeds.ZipstudyFeeds.Skip1,a,b=>a.Dateb;值得修复的一件事是我发现这个版本更容易阅读的条件:studyFeeds.ZipstudyFeeds.Skip1,a,b=>a.Datetrue;就我个人而言,我不能说我感觉到所有测试都是正确的与任何测试都是错误的之间有任何清晰的区别,额外的lambda对我来说似乎是不必要的,但我猜无论什么东西会让你的船漂浮。@StackHola我想你有一个拼写错误:b=>true总是返回true忽略b是假还是真,我想你的意思是b=>b@SteveCadwallader是的,你是对的,不能重新编辑。正确的形式是:studyFeeds.ZipstudyFeeds.Skip1,a,b=>a.Dateb;一件值得修复的事情是应该修复的条件