开发者

How to pass value by reference in C#?

开发者 https://www.devze.com 2022-12-18 06:54 出处:网络
I have the following linq code. searchResults = (from item1 in searchResults join item2 in coll on item1.skuID equals item2.Skuid

I have the following linq code.

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

The variable searchResults is passed in the method as a generic List. The linq segment above filters the list. When returned from the method I expect the list to be开发者_如何转开发 modified but the reference remained unchanged as it was passed in. How do I achieve modifying my reference, not a copy? Thanks.


You should return the filtered result, so if your method looks like this:

public void Filter(List<Item> searchResults)

change it to:

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

and then return the result instead of assigning it to the variable. In other words, change this:

searchResults = (from item1 in searchResults

to this:

return (from item1 in searchResults

In your call, change from:

Filter(list)

to:

list = Filter(list).ToList();

This gives you maximum reusability, as you can pass in a list and trust the method not to change it, leaving the choice whether to place it into a new variable, or replacing the original list, up to you.

Also, as indicated by Fredrik in his comments, the call to .ToList() in the Linq query should be removed as well, and possible you might want to change the input parameter to be IEnumerable as well.

Let me summarize.

If you have code like this:

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);

and want to make list become updated, I'd change the code to this:

       __ 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();


I see you've already got an answer to your question. But you might be curious as to why you cannot use a ref parameter in a query comprehension.

The reason is because the query comprehension expression represents the query, not its results. It represents a deferred execution of the query. So, suppose we allowed that:

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()) { ... }
}

What does this do? The query is not executed until after Blob returns, but the query refers to a local variable reference on a frame that no longer exists.

The compiler has no way of knowing that you are not in this situation every time a ref is used in a query, so it forbids it entirely.


You're assigning the searchResults parameter to point to a new List instance.

To see the change in the calling method, you'll need to make it a ref parameter.

Alternatively, you could modify the list in-place, like this:

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);


You need to mark the searchResults parameter as ref.

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

Edit

Since you're using the list in a query (which is an anonymous method), you'll have to modify the list in-place rather than a ref parameter.

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);

It looks like SLaks got to this answer more quickly.


The variable searchResults needs to be passed in as a [ref][1] parameter.

The method signature would look like this.

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

To call it you'll need to use ref as well:

filter(ref myResults, stuff);
0

精彩评论

暂无评论...
验证码 换一张
取 消