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 ?

3
  • 4
    Why do you have a ref there in the first place? Commented Jul 25, 2014 at 15:23
  • 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. Commented Jul 25, 2014 at 15:58
  • 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. Commented Jul 25, 2014 at 19:00

2 Answers 2

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) 
Sign up to request clarification or add additional context in comments.

1 Comment

or var foo = new List<Foo>() as IList<Foo>;
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.

4 Comments

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.aspx
I know that. Which is why I answered the question asked, but I also wonder what the purpose of the ref is as well.
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.
Ah, see what you mean, rewriting that passage now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.