Passing List by ref when IList by ref is the method signature
Asked Answered
E

2

5

I am having trouble with the code below. I want my method to take an IList, not a List But am I misguided?

Here is my method:

public void DoFoo( ref IList<Foo> thingy) {}

Here is the declaration and call:

var foo = new List<Foo>();
DoFoo( ref foo)

Why will this not compile? foo definitely implements IList If is because the compile will have to cast from List to IList ?

Eddington answered 25/7, 2014 at 15:18 Comment(3)
Why do you have a ref there in the first place?Pyramidal
See also blogs.msdn.com/b/ericlippert/archive/2009/09/21/…. But Lasse is right; this code is almost certainly wrong. If you want to pass a list, pass a reference to a list, not a reference to a variable of type list. The former is IList<T>, the latter is ref IList<T>; they are very different.Kutch
The normal resolution to this problem is to instead use public IList<Foo> DoFoo( IList<Foo> thingy) {} and then use IList<Foo> foo = new List<Foo>();foo = DoFoo(foo);. Still ugly, though.Massage
V
7

Type inference gets in the way here. The var is equivalent to declaring a List directly but you want an IList. You'll have to write the expected type explicitly in your declaration.

IList<foo> foo = new List<Foo>();
DoFoo( ref foo)
Vendace answered 25/7, 2014 at 15:20 Comment(1)
or var foo = new List<Foo>() as IList<Foo>;Infallibilism
P
4

The reason it doesn't compile is that the ref allows the method to do this:

public void DoFoo( ref IList<Foo> thingy)
{
    thingy = new Foo[10];
}

Arrays implement IList<T>, but they're not List<T>, and that's why the compiler refuses to compile the code.

You have a parameter that refers to a variable of a specific type, in this case List<Foo>, and you can't stuff other types of collections in there, unless they inherit from List<Foo>.

There is one way to circumvent this, just copy the list to a variable of the right type, but you also need to decide what happens if the method actually replaces the contents of that variable.

In other words, you can do this:

IList<Foo> il = foo;
DoFoo(ref il);
// what if il is a new reference here now?

As already mentioned in another answer, objects (and thus lists in this case) are already references. Are you sure you need the ref in the first place? Let me clarify. Objects in .NET are reference types, which means you pass a reference to the object. Using a ref parameter allows you to pass a parameter by reference, which is different.

Passing a reference allows the method to access the same object as the outside world. Passing by reference allows the method to access the variable in the outside world.

Pyramidal answered 25/7, 2014 at 15:22 Comment(4)
As it was said on the other answer, passing by reference and passing a reference type by value is not the same. Default behavior is to pass by value. msdn.microsoft.com/en-us/library/s6938f28.aspxVendace
I know that. Which is why I answered the question asked, but I also wonder what the purpose of the ref is as well.Pyramidal
I figured you would know, but I'm clarifying because of your "objects (and thus lists in this case) are already passed by reference" line.Vendace
Ah, see what you mean, rewriting that passage now.Pyramidal

© 2022 - 2024 — McMap. All rights reserved.