0

Can anyone please tell me why method parameter IEnumerable returns null even though it is assigned at the callee method. We all know interface is an reference type.

Dont consider the logic. I just replaced my business logic to suit the scenario

static void Main()  
{   
  IEnumerable<int> gEnumerable = null;  
  Foo(gEnumerable);    //here param gEnumerable always returns null even if i assign  value at my Foo(), why is it so???  
}    

static IEnumerable<int> Bar(List<int> lst)         
{  
  return lst.Select(k => k);  
}  

private  static  void Foo(IEnumerable<int> response)  
{  
  response = Bar(new List<int> { 1, 2, 3, 4, 5, 6 });  
}

Kindly explain me regarding this

Oded
  • 489,969
  • 99
  • 883
  • 1,009
Karthik
  • 1,064
  • 2
  • 16
  • 33
  • This is why our founding fathers, like Tony Hoare and Edgar Dijkstra, gave us methods with a return value type other than void. Use the *return* statement here, it fills the void. – Hans Passant Aug 11 '12 at 21:23

3 Answers3

4

We all know interface is an reference type.

You need to study up a bit on how arguments are passed in C#. Everything is passed by value (by default). In the case of a reference type, the reference is copied when passed to the function (because the reference is its value). So, you are assigning a new value to a copy of a reference and it is not seen by the caller.

If you truly need to assign a completely new value to the reference then you must use either the ref or out specifier. If your method guarantees that it will assign a new value to its input then use out.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • Oh..But when i looked into reference type tutorial in msdn i am able to find interface in reference types not in value types. – Karthik Aug 11 '12 at 20:46
  • @erwe: Actually, it's more complicated than I made it out to be. See: http://stackoverflow.com/questions/8540925/do-interface-variables-have-value-type-or-reference-type-semantics – Ed S. Aug 11 '12 at 20:48
  • An interface variable or parameter is always a reference - even if the object is a value type (in which case it gets boxed automatically). – Lucero Aug 11 '12 at 20:48
  • @Lucero: Yep, I was wrong, that's why I removed that sentence. I looked into it a bit after posting and noticed my mistake. Learned something new. – Ed S. Aug 11 '12 at 20:50
  • Good that you fixed it - I was going to downvote... ;) The reason for interfaces always being references is very simple: since interfaces can be implemented by any class or struct it has to be a reference (the compiler cannot know in advance how large the data needs to be, so a reference is a must). – Lucero Aug 11 '12 at 20:53
  • @Lucero: Yep, makes sense. I hadn't thought about it too much before as I have never implemented an interface with a value type. That's why I answer questions here, always learning new things, even when the question seems trivial. :) – Ed S. Aug 11 '12 at 20:59
3

You have to pass response by reference, otherwise you are not changing the original reference passed - you should avoid this approach if you can avoid it:

static void Main()  
{   
  IEnumerable<int> gEnumerable = null;  
  Foo(ref gEnumerable);    
} 
private  static void Foo(ref IEnumerable<int> response)  
{  
   response = Bar(new List<int> { 1, 2, 3, 4, 5, 6 });  
}

Why not just redesign and make Foo return the value you want though? That is much cleaner imo.

private  static IEnumerable<int> Foo()  
{  
   return Bar(new List<int> { 1, 2, 3, 4, 5, 6 });  
}
BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
2

You need to pass the argument using the Ref keyword so that you modify gEnumerable instead of create new enumerations that will be disposed as soon as they leave scope.

static void Main()  
{   
  IEnumerable<int> gEnumerable = null;  
  Foo(ref gEnumerable);    //here param gEnumerable always returns null even if i assign       value at my Foo(), why is it so???  
}    

static IEnumerable`<int>` Bar(List`<int>` lst)         
{  
   return lst.Select(k => k);  
}  

private  static  void Foo(ref IEnumerable`<int>` response)  
{  
  response = Bar(new List`<int>` { 1, 2, 3, 4, 5, 6 });  
}
Brian Dishaw
  • 5,767
  • 34
  • 49