传递 Func其中 TResult 未知
注意:请适当地重新标记和/或重新命名
我有一个类 FooEnumerator
,它包装 Foo
并实现 IEnumerable
>。 Foo
表示一个树状数据结构,枚举的 FooEnumerator
是当前节点的子节点。
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
的任何和所有属性进行排序。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
嗯,您无法创建
Expression>
类型的成员委托变量,因为TKey
从未被指定。但是,您可以创建Expression>
类型的成员,这可能足以满足您的目的。当然,您可能还需要更改FooEnumerator
构造函数以接受此签名。编辑:其他人建议参数化您的
FooEnumerator
,以便它接受TKey
。您当然可以这样做,但您应该意识到出现的问题:FooEnumerator
FooEnumerator
的代码都将彻底失败。 T>
必须具有类型T
的先验知识。但是,您可以实现一个非通用接口IFooEnumerator
来处理这个问题。FooEnumerator
、FooEnumerator
、FooEnumerator
,等等。Well, you can't create a member delegate variable of type
Expression<Func<Foo,TKey>>
sinceTKey
is never specified. However, you could create a member of typeExpression<Func<Foo,IComparable>>
which may suffice for your purposes. You could need to change yourFooEnumerator
constructor to accept this signature as well, of course.EDIT: Others have suggested parameterizing your
FooEnumerator
so that it accepts aTKey
. You can certainly do this, but you should be aware of the issues that emerge:FooEnumerator<T>
has to have a-priori knowledge of the typeT
. You could, however, implement a non-generic interfaceIFooEnumerator
to deal with that.FooEnumerator<T>
,FooEnumerator<T1,T2>
,FooEnumerator<T1,T2,T3...>
, and so on.您还可以参数化您的枚举器:
不过,我建议使用
IComparable
针对接口进行编程。You can also parameterize your Enumerator:
I recommend programming against the interface using
IComparable
however.