C# 如何更正泛型排序代码以对可为空的类型进行排序

C# 如何更正泛型排序代码以对可为空的类型进行排序,c#,.net,generics,sorting,nullable,C#,.net,Generics,Sorting,Nullable,我们一直在使用这种方法对通用列表进行排序。最近,当T中的目标属性是可空类型(decimal?)时,我们注意到错误的结果。你知道怎么纠正吗 public void SortList<T>(List<T> dataSource, string fieldName, SortDirection sortDirection) { PropertyInfo propInfo = typeof(T).GetProperty(fieldName); Comparison

我们一直在使用这种方法对通用列表进行排序。最近,当T中的目标属性是可空类型(decimal?)时,我们注意到错误的结果。你知道怎么纠正吗

public void SortList<T>(List<T> dataSource, string fieldName, SortDirection sortDirection)
{
    PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
    Comparison<T> compare = delegate(T a, T b)
    {
        bool asc = sortDirection == SortDirection.Ascending;
        object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
        object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);

        return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
    };
    dataSource.Sort(compare);
}
public void排序列表(列出数据源、字符串字段名、排序方向或排序方向)
{
PropertyInfo-propInfo=typeof(T).GetProperty(fieldName);
比较=代表(T a,T b)
{
bool asc=sortDirection==sortDirection.升序;
对象值a=asc?propInfo.GetValue(a,null):propInfo.GetValue(b,null);
对象值b=asc?propInfo.GetValue(b,null):propInfo.GetValue(a,null);
返回值a是i可比较的?((i可比较)值a)。与(值b)比较:0;
};
排序(比较);
}
以上代码摘自Phil Hustead的文章“按对象属性名称对通用列表和IEnumerables进行排序”

例如,对于具有可为空的十进制属性小时数的my Employee对象

可空小时数 107,空,8152,64,空 有点 8,空,64,空,107,152

我认为空值应该排序到列表的开头或结尾。

将方法更改为

public static void SortList<T>(List<T> dataSource, string fieldName, SortDirection sortDirection)
{
    PropertyInfo propInfo = typeof(T).GetProperty(fieldName);
    Comparison<T> compare = delegate(T a, T b)
    {
        bool asc = sortDirection == SortDirection.Ascending;
        object valueA = asc ? propInfo.GetValue(a, null) : propInfo.GetValue(b, null);
        object valueB = asc ? propInfo.GetValue(b, null) : propInfo.GetValue(a, null);

        if(valueA == null)
        {
            if(valueB == null)
            {
                return 0;
            }
            else
            {
                return asc ? -1 : 1;
            }
        }
        if(valueB == null)
        {
            return asc ? 1 : -1;
        }

        return valueA is IComparable ? ((IComparable)valueA).CompareTo(valueB) : 0;
    };
    dataSource.Sort(compare);
}
publicstaticvoidsortlist(列出数据源、字符串字段名、SortDirection-SortDirection)
{
PropertyInfo-propInfo=typeof(T).GetProperty(fieldName);
比较=代表(T a,T b)
{
bool asc=sortDirection==sortDirection.升序;
对象值a=asc?propInfo.GetValue(a,null):propInfo.GetValue(b,null);
对象值b=asc?propInfo.GetValue(b,null):propInfo.GetValue(a,null);
如果(valueA==null)
{
如果(valueB==null)
{
返回0;
}
其他的
{
返回asc?-1:1;
}
}
如果(valueB==null)
{
返回asc?1:-1;
}
返回值a是i可比较的?((i可比较)值a)。与(值b)比较:0;
};
排序(比较);
}
主要问题是,您正在检查
valueA
是否仅检查
IComparable
,如果
valueA==null
,则无论
valueB
中的是什么,比较都会返回相等的对象。当可空值被装箱时(这正是这里发生的情况),它由实际值或
null
表示,上面(最后)支持可空值的示例对我的列表非常有用,但仅在某些情况下。My CustomType包含四个字段,其中两个是字符串类型,两个是DateTime?(可为空)类型

当我对任意一个字符串值进行排序时,效果都很好。但是,当我对其中一个可为空的DateTime排序时?值,它对一个日期时间进行排序?值,但它“丢失”字符串值的信息

我只剩下一个按指定日期时间排序的列表?值,并且仍然包含其他日期时间?值,但清空了字符串值


这里有什么想法吗?

请提供一些您发现实际结果和您想要的结果都有问题的示例输入。为什么在处理
List
时还要使用您的方法呢?只需使用List的
Sort
方法,一个默认的比较器就可以了。当使用“Value”(这是我能想到的唯一属性名)作为
fieldName
调用此方法时,您将得到一个
TargetException
。是的,但这个问题有点让人困惑。OP是使用可空属性对对象进行排序,而不是使用
decimal?
T
Employee
fieldName
Hours
Hours
decimal?
)谢谢。非常好的回答和非常有用的解释。啊哈,没有注意到OP的编辑。我以为OP真的想对一个
decimal?
列表进行排序。