Linq 可数与防御性编程

Linq 可数与防御性编程,linq,defensive-programming,iorderedenumerable,Linq,Defensive Programming,Iorderedenumerable,我喜欢防御性编程。 我讨厌抛出异常,但这不是我问题的主题 我对linQ进行了扩展,以便能够使用列名执行order by public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression) 公共静态IEnumerable OrderBy(此IEnumerable列表,字符串排序表达式) 对于防御性编程,如果列名无效,此方法将返回给定的

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

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

        public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
公共静态IEnumerable OrderBy(此IEnumerable列表,字符串排序表达式)
对于防御性编程,如果列名无效,此方法将返回给定的可枚举项

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

        public static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> list, string sortExpression)
public静态IORDerenumerable OrderBy(此IEnumerable列表,字符串排序表达式)
我需要返回一个IORDerenumerable。 我的问题是保留我的防御性编程功能:如果列名无效,我必须返回给定的集合

有没有干净的方法可以做到这一点?我想的都是一些技巧:

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

您可以任意订购。若列不存在,只需保持输入的可枚举性不变。为此,请创建为所有元素返回相同值的键选择器

见示例:

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();
    }
}
使用系统;
使用System.Linq;
使用System.Collections.Generic;
运用系统反思;
静态类程序
{
公共静态IORDerenumerable OrderBy(此IEnumerable列表,字符串sortExpression),其中T:class
{
Func键选择器=(元素)=>
{
PropertyInfo pi=typeof(T).GetProperty(sortExpression,typeof(Int32));
if(pi==null)
返回0;//为所有元素返回相同的键
返回Int32.Parse(pi.GetValue(elem,null.ToString());
};
返回列表.OrderBy(keySelector);
}
静态void Main(字符串[]参数)
{
//创建要排序的字符串数组。
字符串[]水果={“杏”、“橙”、“香蕉”、“芒果”、“苹果”、“葡萄”、“草莓”};
//按“列”长度排序
foreach(水果中的字符串s.OrderBy(“长度”))
控制台。写入线(s);
Console.WriteLine();
//按不存在的列排序
foreach(水果中的字符串s.OrderBy(“ength”))
控制台。写入线(s);
Console.ReadKey();
}
}

请注意,本例中的“列”类型为Int32,只是元素的属性之一。您可以改为使用String类型,或者创建泛型方法。请注意,键始终相同时的顺序(在我的示例中为0)不能保证输出的顺序与输入的顺序相同。我想是一样的,但在这种情况下,正式的顺序可能是不确定的。如果列名错误,则不确定的顺序不是问题,只要结果与输入相同。我只是不想检查结果是否为null或捕获异常;)谢谢你的回答,很高兴它对你也有帮助。我会尽快测试它。如何以更具防御性的方式返回与请求内容无关的输出,而不是抛出异常、在特定层捕获异常、以适合程序类型的方式显示异常,然后更确信其他代码没有引入bug,假设排序可枚举项的方法排序可枚举项?这似乎与防御性编程截然相反。