C# 如何更正泛型排序代码以对可为空的类型进行排序
我们一直在使用这种方法对通用列表进行排序。最近,当T中的目标属性是可空类型(decimal?)时,我们注意到错误的结果。你知道怎么纠正吗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
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?
列表进行排序。