[英]out / ref parameter for delegate
代表:
return delegate( IQueryable<MySearchResultItem> query, Expression<Func<MySearchResultItem, object>> lambda, Wrapper wrapper)
{
wrapper.query = query.OrderBy(lambda);
query = query.OrderBy(lambda);
};
包装类:
public class Wrapper
{
public IQueryable<MySearchResultItem> query { get; set; }
}
当我执行这个委托时,我希望在这个函数结束后更改查询,但事实并非如此。 所以我假设通过值传递的查询(而不是通过引用)
但是当我为这个查询创建一个包装类时,将查询添加到包装类中并将其传递给它。 然后在完成此方法之后,包装类中的查询已更改(因此,此包装类是通过引用传递的?)
这里发生了什么 ?
它通过引用传递,但您不是在引用上操作而是覆盖它。 当你为指针分配一个新地址而不是操作指针的值时,就像在C中一样。 它适用于包装类,因为您处理引用而不是覆盖它。
如果要修改引用,请使用ref
运算符。
return delegate( ref IQueryable<MySearchResultItem> query,
编辑:当然,这需要具有匹配的委托签名,它不适用于Func<T1,T2, TResult>
。
public delegate void MyDelegate(ref IQueryable<object> query, Expression<Func<object, object>> lambda);
private MyDelegate Create()
{
return delegate(ref IQueryable<object> query, Expression<Func<object, object>> lambda)
{
query = query.OrderBy(lambda);
};
}
您可能将C#“引用”与C ++“引用”混合在一起。
在你的代码, query
是通过引用传递,这意味着参考值query
是按值传递。 因此,更改query
将更改引用引用的值。 但是,更改引用本身不起作用。
query
是不可变的 - 没有办法改变这个值。 您只能创建一个新查询,其中包含旧查询。 而这正是OrderBy
所做的 - 它不会改变query
。 这是LINQ和C#中类似功能方法的核心功能之一 - 可变代码通常难以处理,所以你要避免它,特别是在接口上。
所以你需要做的是通过引用传递引用,而不是通过值。 这正是你通过提供Wrapper
类所做的。 也可以使用ref
关键字来执行此操作,但这完全没有必要,而且在您的情况下很难处理。 ref
只对值类型有意义,尽管有一些有用的案例甚至是引用类型; 但是,它们非常罕见。
但最好和最简单的方法是简单地遵循简单的原则:不要改变任何东西,只返回包含变化的对象。 让您的委托返回查询,而不是修改参数:
delegate IQueryable<...> YourDelegate(IQueryable<...> query);
IQueryable<...> YourMethod(IQueryable<...> query)
{
return query.OrderBy(...);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.