Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 委托的out/ref参数_C#_Pass By Reference_Pass By Value - Fatal编程技术网

C# 委托的out/ref参数

C# 委托的out/ref参数,c#,pass-by-reference,pass-by-value,C#,Pass By Reference,Pass By Value,代表: return delegate( IQueryable<MySearchResultItem> query, Expression<Func<MySearchResultItem, object>> lambda, Wrapper wrapper) { wrapper.query = query.OrderBy(lambda); query = query.OrderBy(lambda); }; 返回委托(IQueryable查询、表

代表:

return delegate( IQueryable<MySearchResultItem> query, Expression<Func<MySearchResultItem, object>> lambda, Wrapper wrapper)
{
    wrapper.query = query.OrderBy(lambda);
    query = query.OrderBy(lambda);
};
返回委托(IQueryable查询、表达式lambda、包装器)
{
wrapper.query=query.OrderBy(lambda);
query=query.OrderBy(lambda);
};
包装类:

public class Wrapper
{
    public IQueryable<MySearchResultItem> query { get; set; }
}
公共类包装器
{
公共IQueryable查询{get;set;}
}
当我执行此委托时,我希望在该函数结束后更改查询,但它没有。因此,我假设查询按值传递(而不是按引用传递)

但是,当我为这个查询创建一个包装器类时,将查询添加到包装器类,并将其传递。然后在这个方法完成之后,包装类内部的查询已经被更改(那么这个包装类是通过引用传递的?)


这里发生了什么?

它是通过引用传递的,但您不是在引用上操作,而是覆盖它。这与C语言中为指针分配新地址而不是对指针的值进行操作类似。它与包装类一起工作,因为您处理引用而不是覆盖它

如果还想修改参考,请使用
ref
运算符

return delegate( ref IQueryable<MySearchResultItem> query,
返回委托(参考IQueryable查询,
编辑:当然,这需要具有匹配的代理签名,并且它不能与
Func
一起使用

公共委托void MyDelegate(引用可查询的查询,表达式lambda);
私有MyDelegate创建()
{
返回委托(引用IQueryable查询,表达式lambda)
{
query=query.OrderBy(lambda);
};
}
<代码> > p>您可以将C++引用“与引用”混合起来。

在代码中,
query
是通过引用传递的,这意味着对
query
的值的引用是通过值传递的。因此,更改
query
将更改引用所引用的值。但是,更改引用本身并没有任何作用

query
是不可变的-无法更改值。您只能创建一个新查询,该查询本身包含旧查询。这正是例如
OrderBy
所做的-它不会更改
query
。这是LINQ和C中类似函数方法的核心功能之一-可变代码就是ge一般来说,很难用一般的方式处理,所以您希望避免它,尤其是在接口上

因此,您需要做的是通过引用而不是通过值来传递引用。这正是您通过提供
包装器
类所做的。也可以使用
ref
关键字来实现这一点,但在您的情况下,这完全是不必要的,而且很难处理。
ref
只对值类型有意义,尽管对于引用类型也有一些有用的例子,但它们非常罕见

但最好、最简单的方法是简单地遵循以下简单原则:不更改任何内容,只返回包含更改的对象。让您的委托返回查询,而不是修改参数:

delegate IQueryable<...> YourDelegate(IQueryable<...> query);

IQueryable<...> YourMethod(IQueryable<...> query)
{
  return query.OrderBy(...);
}
delegate IQueryable您的委托(IQueryable查询);
IQueryable方法(IQueryable查询)
{
返回query.OrderBy(…);
}

您将查询重新分配给query.OrderBy(lambda)。这不会创建新的引用,并且输入查询参数也不会因此发生更改吗?这给了我一个错误:“不应使用'ref'关键字声明参数1”@当然是Timon,因为这是一个可怕的想法。只需按照惯例,像其他人一样返回新的查询。您正在处理函数式编程,并且查询是不可变的。返回一个新的东西,不要更改旧的东西。那么,您可以发布其余的代码吗?它假设您必须匹配某个sig代表的天性。@Luaan我同意这是一个可怕的想法。但是我认为当他没有写扩展时,他有他的理由。所以我所做的只是试图解释为什么他想做的任何事情都不起作用。
delegate IQueryable<...> YourDelegate(IQueryable<...> query);

IQueryable<...> YourMethod(IQueryable<...> query)
{
  return query.OrderBy(...);
}