如何在C#中通过引用传递值?

时间:2010-01-29 15:20:14

标签: c# linq pass-by-reference

我有以下linq代码。

searchResults = (from item1 in searchResults
              join item2 in coll
              on item1.skuID equals item2.Skuid
              where item2.SearchableValue == value
              select item1).ToList();

变量searchResults作为通用List在方法中传递。上面的linq段过滤列表。当从方法返回时,我希望修改列表但引用在传入时保持不变。如何修改我的引用,而不是副本?感谢。

5 个答案:

答案 0 :(得分:12)

您应该返回已过滤的结果,因此如果您的方法如下所示:

public void Filter(List<Item> searchResults)

将其更改为:

public IEnumerable<Item> Filter(List<Item> searchResults)

然后返回结果而不是将其赋值给变量。换句话说,改变这个:

searchResults = (from item1 in searchResults

到此:

return (from item1 in searchResults

在通话中,请改变:

Filter(list)

为:

list = Filter(list).ToList();

这为您提供了最大的可重用性,因为您可以传入一个列表并信任该方法不要更改它,留下选择是将它放入一个新变量,还是替换原始列表,直到您。

此外,正如Fredrik在他的评论中指出的那样,Linq查询中对.ToList()的调用也应该被删除,并且您可能希望将输入参数更改为IEnumerable。

让我总结一下。

如果你有这样的代码:

public void Filter(List<Item> searchResults)
{
    searchResults = (from item1 in searchResults
                     join item2 in coll
                     on item1.skuID equals item2.Skuid
                     where item2.SearchableValue == value
                     select item1).ToList();
}

...
list = ...
Filter(list);

并希望让list更新,我会将代码更改为:

       __ changed ______        __ changed ______
public IEnumerable<Item> Filter(IEnumerable<Item> searchResults)
{
    return from item1 in searchResults               <-- changed
           join item2 in coll
           on item1.skuID equals item2.Skuid
           where item2.SearchableValue == value
           select item1;                             <-- changed
}

...
list = ...         _ added__
list = Filter(list).ToList();

答案 1 :(得分:7)

我看到你已经得到了问题的答案。但是您可能会对为什么不能在查询理解中使用ref参数感到好奇。

原因是因为查询理解表达式表示查询,而不是其结果。它表示查询的延迟执行。所以,假设我们允许:

IEnumerable<int> Frob(ref int x)
{  return from foo in whatever where foo.bar == x select foo.bar; }

IEnumerable<int> Blob()
{ 
    int y = 123; 
    var r = Frob(ref y);    
    y = 456;
    return r;
}
void Grob()
{
    foreach(int z in Blob()) { ... }
}

这是做什么的?直到Blob返回后才执行查询,但查询引用不再存在的帧上的局部变量引用。

每次在查询中使用ref时,编译器都无法知道你在这种情况下,所以它完全禁止它。

答案 2 :(得分:4)

您正在指定searchResults参数以指向新的List实例。

要查看调用方法的更改,您需要将其设为ref参数。

或者,您可以就地修改列表,如下所示:

var newResults = (from item1 in searchResults
                  join item2 in coll
                  on item1.skuID equals item2.Skuid
                  where item2.SearchableValue == value
                  select item1).ToArray();

searchResults.Clear();
searchResults.AddRange(newResults);

答案 3 :(得分:2)

您需要将searchResults参数标记为ref

public void Foo(ref List<T> searchResults) { ... }

修改

由于您在查询中使用列表(这是一种匿名方法),因此您必须就地修改列表而不是ref参数。

var results = (from item1 in searchResults
               join item2 in coll
               on item1.skuID equals item2.Skuid
               where item2.SearchableValue == value
               select item1).ToList();

searchResults.Clear();
searchResults.AddRange(results);

看起来SLaks更快地得到了这个答案。

答案 4 :(得分:-2)

变量searchResults需要作为[ref][1]参数传递。

方法签名看起来像这样。

//Note you only need to ref the one variable.
void filter(ref List searchResults, object otherParameter)
{
   //LINQ and stuff here
}

要调用它,您还需要使用ref

filter(ref myResults, stuff);