Behavior Explaination

  • Thread starter Thread starter rowe_newsgroups
  • Start date Start date
R

rowe_newsgroups

I was recently asked to explain why the below code set's the property
values in the load method, but the values aren't persisted upon
leaving the load method.

To be honest, I can't think of a great explanation on why it doesn't
work, so I figured I'd post here and see if one of the guru's could
tell me exactly what's happening and why. I'm guessing this has to do
with the fact you need to pass the object by ref, which can't be done
with "this".

Here's a complete console application that demonstrates the behavior:

/////////////////////
using System;

namespace ConsoleApplication1
{
public class Program
{
public static void Main()
{
var fooObject = new FooObject();

fooObject.Load();

Console.WriteLine(fooObject.Name);
Console.WriteLine(fooObject.Description);

Console.Read();
}
}

public class FooObject
{
public string Name { get; set; }
public string Description { get; set; }

public void Load()
{
DALC.LoadFooObject(this);
}
}

public static class DALC
{
public static void LoadFooObject(FooObject fooObject)
{
/*
This of course works, but they don't want to do it
(long story)

fooObject.Name = "name";
fooObject.Description = "some
description";
*/

var temp = new FooObject()
{
Name = "name",
Description = "some description"
};

// This is the issue, the property values are set here,
but not
// persisted once we leave the method.
fooObject = temp;
}
}
}
/////////////////////

Thanks,

Seth Rowe [MVP]
 
rowe_newsgroups said:
public static void LoadFooObject(FooObject fooObject)

When entering LoadFooObject, the local variable fooObject points to a
certain object X in memory.
{
/*
This of course works, but they don't want to do it
(long story)

fooObject.Name = "name";
fooObject.Description = "some
description";
*/

var temp = new FooObject()
{
Name = "name",
Description = "some description"
};

Now temp points to a different object Y in memory.
// This is the issue, the property values are set here,
but not
// persisted once we leave the method.
fooObject = temp;

after this line, fooObject points to Y, just as temp. The original
object X has not changed at all.

C# is not C++ ;-)

Regards,
 
When entering LoadFooObject, the local variable fooObject points to a
certain object X in memory.




Now temp points to a different object Y in memory.




after this line, fooObject points to Y, just as temp.  The original
object X has not changed at all.


C# is not C++ ;-)

Regards,

Thanks for the explaination - I'll forward this on.

By the way, I love the "C# is not C++ ;-)" line :-)

Thanks,

Seth Rowe [MVP]
 
Hi,

As i know, the method parameters by default get passed by value. That means
if You do something like:
DALC.LoadFooObject(referenceToAnObject);
then the LoadFooObject will get a parameter what is a _copy_ of the
reference. This means that no matter what You do with the reference in the
LoadFooObject method, it wont affect the original reference. If You wish to
pass parameters by reference (so You wish to pass a reference to a reference
:D ), You should use ref .

It also seems a bit weird to me that this code tries to change the this
reference. It is not possible that an object change its own identity by
setting the this reference (not just logically, it wont even compile).

Some ideas how to handle this:
1. make fooobject.load static, also DALC.LoadFooObject should return temp
(change var in this case to explicit typename), so as fooobject.load can
return the return value of DALC.LoadFooObject .
2. extract the persisted state of FooObject, making the fooobject a
composition of fooobject and its persistent state, and then You can
use the DALC.LoadFooObject, but pass the state instead of the full object
and use ref.
(These are just ideas, i'm not saying that these are appropriate for Your
context, or even that these are good solutions)

Hope You find this useful.
-Zsolt
 
Hi,

As i know, the method parameters by default get passed by value. That means
if You do something like:
DALC.LoadFooObject(referenceToAnObject);
then the LoadFooObject will get a parameter what is a _copy_ of the
reference. This means that no matter what You do with the reference in the
LoadFooObject method, it wont affect the original reference. If You wish to
pass parameters by reference (so You wish to pass a reference to a reference
:D ), You should use ref .

It also seems a bit weird to me that this code tries to change the this
reference. It is not possible  that an object change its own identity by
setting the this reference (not just logically, it wont even compile).

Some ideas how to handle this:
1.  make fooobject.load static, also DALC.LoadFooObject should return temp
(change var in this case to explicit typename), so as  fooobject.load  can
return the return value of DALC.LoadFooObject .
2. extract the persisted state of FooObject, making the fooobject a
composition of fooobject and its persistent state, and then You can
use the DALC.LoadFooObject, but pass the state instead of the full object
and use ref.
(These are just ideas, i'm not saying that these are appropriate for Your
context, or even that these are good solutions)

Hope You find this useful.
-Zsolt

Yeah, I've already given them a work around, they were more interested
in the /why/ their idea didn't work. Unfortunately, my "because it's
not possible" explaination wasn't good enough :-)

Thanks,

Seth Rowe [MVP]
 
I was recently asked to explain why the below code set's the property
values in the load method, but the values aren't persisted upon
leaving the load method.

To be honest, I can't think of a great explanation on why it doesn't
work, so I figured I'd post here and see if one of the guru's could
tell me exactly what's happening and why. I'm guessing this has to do
with the fact you need to pass the object by ref, which can't be done
with "this".

You don't pass the object by reference. You pass a reference to
object.

I find it handy to reinforce this by always saying "parameter
fooObject is of type _reference to_ FooObject" rather than "parameter
fooObject is of type FooObject" - and ditto for locals & fields. If
you go through the code line by line, spelling it out that way, it
becomes very clear just what is going on.
 
Back
Top