使用自定义排序比较器的任何给定Linq表达式有两种格式:
格式1
var query =
source
.Select(x => new { x.someProperty, x.otherProperty } )
.OrderBy(x => x, new myComparer());
格式2
var query =
from x in source
orderby x // comparer expression goes here?
select new { x.someProperty, x.otherProperty };
问题:
第二种格式的order-by表达式的语法是什么?
不是问题:
如何使用自定义比较器,如第一种格式所示。
奖励积分:
是否有上面列出的两种Linq格式的实际正式名称?
答案 0 :(得分:20)
第二种格式的order-by表达式的语法是什么?
它不存在。来自orderby clause documentation:
您还可以指定自定义比较器。但是,只有使用基于方法的语法才能使用它。
如何以第一种格式使用自定义比较器。
你写的正确。您可以在撰写时传递IComparer<T>
。
上面列出的两种Linq格式是否有实际的正式名称?
格式1称为“基于方法的语法”(from previous link),格式2为“查询表达式语法”(来自here)。
答案 1 :(得分:2)
如何使用自定义比较器,如第一种格式所示。
您无法使用该格式的自定义比较器。
上面列出的两种Linq格式是否有实际的正式名称?
格式1是方法语法,格式2是“查询语法”,
答案 2 :(得分:2)
<强>问题:强>
这在查询语法中是不可能的,因为没有重载。
不是问题:
只有在使用反射来比较对象时才能使用具有匿名类型的比较器,最好使用类型化实现进行比较。
如果您不想创建类型化实现,可以使用Tuple
:
var query =
source
.Select(x => new Tuple<string, int>(x.someProperty, x.otherProperty))
.OrderBy(x => x, new MyComparer());
public class MyComparer : IComparer<Tuple<string, int>>
{
public int Compare(Tuple<string, int> x, Tuple<string, int> y)
{
return x.Item1.CompareTo(y.Item1);
}
}
奖励积分:
答案 3 :(得分:2)
这不一定是回答原始问题,但它在某种程度上扩展了概述的一些可能性。我发布这个以防其他人遇到类似的问题。 此处发布的解决方案概述了按选项的通用订单,这在其他情况下可能很有用。在这个例子中,我想按不同的属性对文件列表进行排序。
/// <summary>
/// Used to create custom comparers on the fly
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericCompare<T> : IComparer<T>
{
// Function use to perform the compare
private Func<T, T, int> ComparerFunction { set; get; }
// Constructor
public GenericCompare(Func<T, T, int> comparerFunction)
{
ComparerFunction = comparerFunction;
}
// Execute the compare
public int Compare(T x, T y)
{
if (x == null || y == null)
{
// These 3 are bell and whistles to handle cases where one of the two is null, to sort to top or bottom respectivly
if (y == null && x == null) { return 0; }
if (y == null) { return 1; }
if (x == null) { return -1; }
}
try
{
// Do the actual compare
return ComparerFunction(x, y);
}
catch (Exception ex)
{
// But muffle any errors
System.Diagnostics.Debug.WriteLine(ex);
}
// Oh crud, we shouldn't be here, but just in case we got an exception.
return 0;
}
}
然后在实施中......
GenericCompare<FileInfo> DefaultComparer;
if (SortOrder == SORT_FOLDER_FILE)
{
DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
{
return fr1.FullName.ToLower().CompareTo(fr2.FullName.ToLower());
});
}
else if (SortOrder == SORT_SIZE_ASC)
{
DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
{
return fr1.Length.CompareTo(fr2.Length);
});
}
else if (SortOrder == SORT_SIZE_DESC)
{
DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
{
return fr2.Length.CompareTo(fr1.Length);
});
}
else
{
DefaultComparer = new GenericCompare<FileInfo>((fr1, fr2) =>
{
return fr1.Name.ToLower().CompareTo(fr2.Name.ToLower());
});
}
var ordered_results = (new DirectoryInfo(@"C:\Temp"))
.GetFiles()
.OrderBy(fi => fi, DefaultComparer);
最大的好处是你不需要为每个订单创建一个新的类,你只需连接一个新的lambda。显然,这可以通过各种方式进行扩展,所以希望它可以在某个时间帮助某个人。