Why is ref needed here?

  • Thread starter Thread starter mBird
  • Start date Start date
M

mBird

When I pass my List<> without the ref keyword persons2 is empty (Count = 0
below).
If I add the ref keyword to the caller and the function then Count is
correct.
I don't understand because if I call DeSerialize(persons2, path) don't I by
default send a reference not the actual List<Person> since List is an
object?
Thank you!

//The below works since I have the ref keyword...
class Program
{
private const string path = @"c:\temp\Serialization.xml";

static void Main(string[] args)
{
List<Person> persons = new List<Person>();
persons.Add(new Person("Person", "One"));
persons.Add(new Person("Person", "Two"));
Serialize(persons, path);

List<Person> persons2 = new List<Person>();
DeSerialize(ref persons2, path);
Console.WriteLine(persons2.Count.ToString());

Console.ReadLine();
}

static void DeSerialize(ref List<Person> o, string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
StreamReader xmltext = new StreamReader(path, true);
o = (List<Person>)serializer.Deserialize(xmltext);
xmltext.Close();
}
}
 
Hello,

you need the ref here because you replace the list instance in your
DeSerialize. The XmlSerializer returns a new instance and doesn't populate
your existing instance.

Kind regards,
Henning Krause
 
When I pass my List<> without the ref keyword persons2 is empty (Count=
0
below).
If I add the ref keyword to the caller and the function then Count is
correct.
I don't understand because if I call DeSerialize(persons2, path) don'tI
by
default send a reference not the actual List<Person> since List is an
object?

Don't confuse passing _by_ reference with passing _a_ reference. Even
though there is obvious room for confusion there. :)

Jon Skeet has a nice writeup that may help:
http://www.pobox.com/~skeet/csharp/parameters.html

The DeSerialize() method is setting the variable itself. If all you were
doing is adding new items to the existing List<> object, you wouldn't need
"ref". But you're replacing the instance reference itself, and without
"ref" the caller isn't affected by that operation.

If you don't want to use "ref" and it's okay to do a full iteration of the
List<> before returning, you could do this instead:

static void DeSerialize(List<Person> o, string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
StreamReader xmltext = new StreamReader(path, true);
List<Person> oT = (List<Person>)serializer.Deserialize(xmltext);
o.AddRange(oT);
xmltext.Close();
}

That would modify the existing List<> rather than replacing it entirely.
In that case, only the instance reference is needed, and the "ref" keyword
is not.

Pete
 
Just to add that thought this is a reference type, parameter passing still
applies :
- either you work on a *copy* of the reference (pointer), in this case the
reference you altered inside your function won't be seen outside (will be
still the persons2 you initialized before the call and that contains no
items).
- either you work on the reference itself and then the reference you altered
inside your function will be visible outside as "persons2"

This is also why it doesn't not make a difference when you pass a collection
and just add items to it (having a copy of the reference or a real reference
doesn't make a difference here as they'll both point to the same object
instance, you see a difference only when you change the reference itself).

--
Patrice

Henning Krause said:
Hello,

you need the ref here because you replace the list instance in your
DeSerialize. The XmlSerializer returns a new instance and doesn't populate
your existing instance.

Kind regards,
Henning Krause

mBird said:
When I pass my List<> without the ref keyword persons2 is empty (Count =
0 below).
If I add the ref keyword to the caller and the function then Count is
correct.
I don't understand because if I call DeSerialize(persons2, path) don't I
by default send a reference not the actual List<Person> since List is an
object?
Thank you!

//The below works since I have the ref keyword...
class Program
{
private const string path = @"c:\temp\Serialization.xml";

static void Main(string[] args)
{
List<Person> persons = new List<Person>();
persons.Add(new Person("Person", "One"));
persons.Add(new Person("Person", "Two"));
Serialize(persons, path);

List<Person> persons2 = new List<Person>();
DeSerialize(ref persons2, path);
Console.WriteLine(persons2.Count.ToString());

Console.ReadLine();
}

static void DeSerialize(ref List<Person> o, string path)
{
XmlSerializer serializer = new XmlSerializer(typeof(List<Person>));
StreamReader xmltext = new StreamReader(path, true);
o = (List<Person>)serializer.Deserialize(xmltext);
xmltext.Close();
}
}
 
Back
Top