【问题标题】:IOrderedEnumerable and defensive programmingIOrderedEnumerable 和防御性编程
【发布时间】:2009-11-24 18:20:44
【问题描述】:

我喜欢防御性编程。 我讨厌抛出异常,但这不是我的问题。

我对 linQ 进行了扩展,以便能够使用列名执行订单

        public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)

使用防御性编程,如果列名无效,此方法将返回给定的枚举。

现在我需要使用 ThenBy 执行 二次排序。 所以我需要那个签名:

        public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)

我需要返回一个 IOrderedEnumerable。 我的问题是保留我的防御性编程功能:我必须返回给定的集合是列名无效。

有没有一种干净的方法来做到这一点?我在想的只是一些技巧:

  • 使用反射按找到的第一个属性排序,这是有风险的,因为该属性可能不允许排序
  • 实现我自己的 IOrderedEnumerable,这也有风险,因为我在 IQueryable 或 IList 上执行排序,然后执行其他 LinQ 操作,所以我担心副作用。

还有意见/建议? 谢谢

【问题讨论】:

  • 如何返回与所要求的内容无关的输出,其被要求的方式比引发异常更具防御性,在特定层捕获它,以适合的方式显示它程序的类型,然后更确信其他代码没有引入错误,假设订购可枚举的方法订购可枚举?这似乎与防御性编程完全相反。

标签: linq defensive-programming iorderedenumerable


【解决方案1】:

您可以进行任何订购。如果列不存在,只需让您的输入像以前一样可枚举。为此,请创建为所有元素返回相同值的键选择器。

查看示例:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;

static class Program
{
    public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression) where T : class
    {
        Func<T, Int32> keySelector = (elem) =>
        {
            PropertyInfo pi = typeof(T).GetProperty(sortExpression, typeof(Int32));
            if (pi == null)
                return 0; // return the same key for all elements

            return Int32.Parse(pi.GetValue(elem, null).ToString());
        };

        return list.OrderBy(keySelector);
    }

    static void Main(string[] args)
    {
        // Create an array of strings to sort.
        string[] fruits = { "apricot", "orange", "banana", "mango", "apple", "grape", "strawberry" };

        // Sort by "column" Length
        foreach (string s in fruits.OrderBy<string>("Length"))
            Console.WriteLine(s);
        Console.WriteLine();

        // Sort by non-existing column
        foreach (string s in fruits.OrderBy<string>("ength"))
            Console.WriteLine(s);
        Console.ReadKey();
    }
}

【讨论】:

  • 请注意,此示例中的“列”具有 Int32 类型,并且只是元素的属性之一。你可以使用 String 类型,或者创建一个泛型方法。
  • 请注意,当键始终相同时排序(在我的示例中为 0)不能保证输出与输入具有相同的顺序。我认为它会是一样的,但在这种情况下,正式的顺序可能是不确定的。
  • 如果您的列名错误,未确定的顺序不是问题,只要结果与输入相同即可。我只是不想检查结果是否为空或捕获异常;)感谢您的回答,很高兴它也对您有所帮助。我会尽快测试的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多