注意:请适本地重新标记和/或重命名
我有课,FooEnumerator
,它包装了一个 Foo
并实现 IEnumerable<FooEnumerator>
. Foo
s 代表树状数据结构,FooEnumerator
枚举出来的s是当前节点的子节点。
Foo
是供应商提供的数据对象。 FooEnumerator
实现了一堆自定义过滤代码。
class FooEnumerator : IEnumerable<FooEnumerator>
{
public Foo WrappedNode { get; private set; }
public string Name { get { return WrappedNode.Name; } }
public int Id { get{ return WrappedNode.Id; } }
public DateTime Created { get{ return WrappedNode.Created; } }
public FooEnumerator(Foo wrappedNode)
{
WrappedNode = wrappedNode;
}
public IEnumerator<FooEnumerator> GetEnumerator()
{
foreach (Foo child in this.GetChildren())
if(FilteringLogicInHere(child))
yield return new FooEnumerator(child);
}
...
}
我希望能够使用给定的(任意)表达式对树的每个级别进行排序,该表达式在顶层 FooEnumerator
时定义。已创建,并将此表达式传递给每个新枚举的项目以供使用。
我想使用 lambda 定义排序表达式,就像使用 OrderBy 函数一样。事实上,我打算将 lambda 传递给 OrderBy
.
OrderBy 的签名是
OrderBy<TSource, TKey>(Func<TSource, TKey> keySelector)
哪里TKey
是给定 Func
的返回类型, 但它是方法签名中的类型参数,并在编译时计算出来。
示例用法
var x = GetStartingNode();
var sort = n => n.DateTime;
var enu = new FooEnumerator(x, sort);
var sort2 = n => n.Name;
var enu2 = new FooEnumerator(x, sort2);
然后排序表达式将存储在一个类变量中,并且 FooEnumerator
会像这样工作:
// pseudo-implementation
private Expression<Func<Foo, TKey>> _sortBy;
public FooEnumerator(Foo wrappedNode, Expression<Func<Foo, TKey>> sortBy)
{
WrappedNode = wrappedNode;
_sortBy = sortBy;
}
public IEnumerator<FooEnumerator> GetEnumerator()
{
foreach (Foo child in this.GetChildren().OrderBy(_sortBy))
if(FilteringLogicInHere(child))
yield return new FooEnumerator(child);
}
在此用例中如何指定 TKey 的类型(隐式或显式)?
我不想对其进行硬编码,因为我希望能够对底层 Foo
的所有属性进行排序.
最佳答案
嗯,你不能创建类型为 Expression<Func<Foo,TKey>>
的成员委托(delegate)变量自 TKey
从未指定。但是,您可以创建类型为 Expression<Func<Foo,IComparable>>
的成员这可能足以满足您的目的。您可能需要更改您的 FooEnumerator
当然,构造函数也接受这个签名。
编辑:其他人建议参数化您的 FooEnumerator
以便它接受 TKey
.你当然可以这样做,但你应该意识到出现的问题:
- 通过对枚举器进行参数化,您就可以完成任务了。任何想要存储
FooEnumerator<T>
的代码必须具有类型的先验知识T
.但是,您可以实现非通用接口(interface)IFooEnumerator
来处理这个问题。 - 如果您想在将来支持对多个字段的排序,那么参数化枚举器会产生问题。C# 不支持具有可变数量类型参数的泛型,这限制了需要的泛型的创建多种任意类型。这个问题比较难处理,因为开始创建
FooEnumerator<T>
很尴尬,FooEnumerator<T1,T2>
,FooEnumerator<T1,T2,T3...>
, 等等。
关于c# - 传递 TResult 未知的 Func<T, TResult>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4189131/