繁体   English   中英

委托的out / ref参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM