Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing List by ref when IList by ref is the method signature

Tags:

c#

list

ilist

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 ?

like image 909
Daniel Williams Avatar asked Jul 25 '14 15:07

Daniel Williams


2 Answers

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.

like image 22
Lasse V. Karlsen Avatar answered Nov 14 '22 23:11

Lasse V. Karlsen


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)
like image 171
dee-see Avatar answered Nov 14 '22 21:11

dee-see