Returning Objects

T

tshad

I am confused on whether pointers are passed or objects are passed on return
of function where we are returning an object. This is important as I need
to have 2 objects and will use one or the other based on certain criteria.
This is mainly because of the difficulty with copying one object to another.

In my case, I am going to build object1 and return it. Then I build object2
and return that. And if object 2 fails some test, I will use object1.

This is why I can't just use a pointer to return it as I would wipe out
object1 if I were pointing at the same object.

For example:

class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

objectPtr = object1;
objectPtr = BuildData();

objectPtr = object2;
objectPtr = BuildData();
}

class B
{
Response BuildData()
{
Response oResponse = new Response();

....

return oResponse;
}
}

class Response
{
stuff
}

In Class A, before I call BuildData()
1) I have an Response object (object1) which is instantiated.
2) I then point to object1 with objectPtr.
3) I then call BuildData() and instantiate another Response object
(oResponse)
4) Before leaving BuildData(), I have 2 distinct objects (object1 and
oResponse).
5) I know that what I really have is 2 pointers (object1 and oResponse)
that point to 2 objects out on the Heap.
6) I now return and pass back oReturn.

What happens here?

A) Does object1 just now point to the object that oResponse was pointing at
and the original object that object1 was pointing at get trashed and garbage
collected since now nothing points at it?

B) Or does the object that oResponse was pointing at get copied to the
object that object1 was pointing at?

C) Something else.

I assume it is "A".

Then when I do the 2nd BuildData(), the same thing happens and object2 will
now point at a new object that the 2nd call to BuildData() created, whereas
the 1st object will just get garbage collected.

If this is the case, I really only have to set up the objects originally as:

Response object1 = null;
Response object2 = null;
Response objectPtr = null;

Since these objects will never be used.

Thanks,

Tom
 
T

tshad

Peter Duniho said:
You would do well to just forget about the word "pointer" in the context
of C#. It has a very specific meaning, used in an "unsafe" context, and
it doesn't come up at all in normal C# code. Use the word "reference"
when referring to a reference.

For a reference type (i.e. a class), a variable NEVER stores the object
itself. A variable of that type ALWAYS is a "reference" to the object.
Hence, "reference type".

Makes sense.
If you assign a new value to a variable of a reference type, the only
thing that happens is value of the variable changes; the object it was
referencing before is unaffected.
[...]
For example:

class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

objectPtr = object1;
objectPtr = BuildData();

objectPtr = object2;
objectPtr = BuildData();
}

Please don't post code like that. The code above is obviously not real
code, because it's not even valid. And in its invalid state, we have no
way to know what those variables actually are or how they are used (are
they locals? statics? instance members? some mix?). After all, they
obviously aren't used as you show them here, so we have to make some guess
as to how they are really used, a guess which may or may not be correct.

Not sure why this isn't valid. I agree there are not publics or private
variables but I was only trying to understand what happened to the variables
and the objects they pointed to.

In this case, Response was a class that I provided and therefore the
object1, object2 and objectPtr were variables of type Response. If I had
started to add other stuff, I would get people saying that my syntax was
incorrect or I forgot to set something private - which is not necessary for
the question. This is more like Pseudo code that closely resembles the code
I had already that was much more complicated and would just confuse the
issue.
In other words, when you post code like that, you might as well not have
posted any code at all.

Why you got it. Your explanation was exactly what I was looking for.

Just before I read your response I was going to make a small change to the
Class A to look like:

class A
{
Response object1 = null;
Response object2 = null;
Response objectPtr = null;

objectPtr = BuildData();
object1 = objectPtr;

objectPtr = BuildData();
object2 = objectPtr;
}

as I found out in my code, as you mentioned, that object1 would not change
after BuildData() returned and set objectPtr to the object it had created.
This should now be what I was trying to do.

Based on what you said, I assume that:

When you return an object, you are just returning a reference to that object
and not actually do anything to the object itself.

So after the first BuildData() and assignment, object1 and objectPtr will
both point to the object that BuildData() created. That object would have
been garbage collected had it not been passed back, but now it has a
reference to it - so it stays around.

So after this is all run I think I would have:

object1 pointing at the object that was created in the 1st BuildData() call.
object2 pointing at the object that was created in the 2nd BuildData() call
objectPtr also pointing at the object that was created in the 2nd
BuildData() call

Thanks,

Tom
As for your question:
[...]
In Class A, before I call BuildData()
1) I have an Response object (object1) which is instantiated.
2) I then point to object1 with objectPtr.
3) I then call BuildData() and instantiate another Response object
(oResponse)
4) Before leaving BuildData(), I have 2 distinct objects (object1 and
oResponse).
5) I know that what I really have is 2 pointers (object1 and
oResponse)
that point to 2 objects out on the Heap.
6) I now return and pass back oReturn.

What happens here?

A) Does object1 just now point to the object that oResponse was pointing
at
and the original object that object1 was pointing at get trashed and
garbage
collected since now nothing points at it?

No. If you assign a new value to "objectPtr", that has ZERO effect on the
"object1" variable. The "object1" variable continues to refer to the
object it was referring to before.
B) Or does the object that oResponse was pointing at get copied to the
object that object1 was pointing at?

No. The REFERENCE to the object that "oResponse" refers to is copied to
the variable "objectPtr". Again, the variable "object1" is unaffected, as
is the object to which it refers.
C) Something else.

Yes.

If we can at least assume that you really do assign the value of "object1"
to the variable "objectPtr" just before calling "BuildData()" and
assigning the return value to "objectPtr", then the net effect is simply
that "objectPtr" winds up referring to the object instantiated in and
returned by "BuildData()". The assignment from "object1" to "objectPtr"
is completely useless and has no lasting effect, because you just
overwrite the value in the next statement, when you call "BuildData()".
I assume it is "A".

Wrong assumption.
Then when I do the 2nd BuildData(), the same thing happens and object2
will
now point at a new object that the 2nd call to BuildData() created,
whereas
the 1st object will just get garbage collected.

No. After the four statements you posted, you will have:

"object1" referring to the first Response instance created
"object2" referring to the second Response instance created
"objectPtr" referring to the fourth Response instance created

And the third Response instance that was created will be eligible for
garbage collection, because it's no longer reachable.
If this is the case, I really only have to set up the objects originally
as:

Response object1 = null;
Response object2 = null;
Response objectPtr = null;

Since these objects will never be used.

Well, it's certainly true that you shouldn't go around instantiating
objects that you don't care about and are never going to actually use.

Beyond that, I can't confirm or refute the statement that you can
initialize your variables to "null" (or just leave them uninitialized, if
they not local variables, since class members are always initialized to
the default value, which is "null" for reference types). It just depends
on what you're really doing; since the code you posted is obviously bogus
code, it's impossible to know what you're really doing. :(

Pete
 
T

tshad

Peter Duniho said:
[...]
class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

objectPtr = object1;
objectPtr = BuildData();

objectPtr = object2;
objectPtr = BuildData();
}

Please don't post code like that. The code above is obviously not real
code, because it's not even valid. [...]

Not sure why this isn't valid.

Because it won't compile.

This was why I didn't want to create an actual program - I don't want to get
caught up in syntax discussions. I explained what I was trying to do at the
beginning of the original post and just wanted to give an example of what I
was trying to do. I didn't want to set up constructors,
public/private/static etc.

In this case, I just was trying to figure out whether pointers/references
were passed or the whole object was being passed. I also explained why I
was asking the question. I didn't want to have to build something and make
sure it ran just to ask a simple question. I assumed that by using "class
A" and "class B" this would be enough to understand that this isn't the code
I was using but a simple representation of what I was trying to achieve.
The problem is that the "class" you posted had no methods, and had program
statements. Program statements are ONLY allowed in a method, but your
class didn't have any methods, even though it did have program statements.
But why is that important to the question. I was only trying to show that I
was calling a method from a different class and that class build the same
type of object I was using in my first object and passed it back Ok, I
could have done something like:

class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

public void test()
{
objectPtr = BuildData();
object1 = objectPtr;

objectPtr = BuildData();
object2 = objectPtr;
}
}

Now I am calling BuildData from a method. The problem is the next question
might be - is this object instantiated or is test static. It could go on
and on. But then we are concerned with the something other than the
question I was trying to get at. I felt it was pretty clear (obviously I
was wrong).
And the problem with that is that without methods, we really don't know
how your variables are declared. They could be locals, they could be
instance members, they could be static members. And the behaviors of each
kind of declaration are subtly different and often important for questions
along the lines of "did this get collected?"
As I mention above, this is the problem. Whether they are locals, instance
members or static member is really irrellevent to the the question. I
wasn't really concerned with the garbage collection, that was just extra
that I mentioned in my questions as I thought that would make it more clear
as to what I wanted to figure out. Mainly, if the object gets passed to the
calling program and then it just disappears and we are done with it or does
it just pass the address of the object to the calling program and now we
have something else pointing at the same object.
If you want to post pseudo-code, then post pseudo-code. Don't post
something that looks like an actual class declaration but which obviously
isn't. If you do post pseudo-code, make sure you are explicit about the
nature of the variables used; that is, state how the variables would be
declared in an actual class. In other words, provide all the context that
would implicitly exist in a valid code example.


Just because I happen to have stumbled across the right meaning and
answered the question does not mean that you included code that was
appropriate for the question.


You did not "make a small change to the Class A to look like" the above.
The above is just as invalid as the code you posted before, and is still
obviously not the code you're really using.
Actually it was a small change. I just move the assignment to after the
call and switched which the order of the statement.
Now, all that said, it's not clear to me why you have "objectPtr" at all.
Why not just assign the returned value into the variable where you want it
in the first place?

See, now you are concerned with the "why" which is not really important to
the question.

But what I am doing later in my code is to comparing the 2 objects based on
addresses and zip codes and will use whichever object is a better match. So
after I determine which object I want (object1 or object2), I will make a
couple of more changes to the object and then pass that back to another
calling program - in this case it would be objectPtr. I am sure there are
better ways of doing this but this is how I decided to do it.
[...]
Based on what you said, I assume that:

When you return an object, you are just returning a reference to that
object
and not actually do anything to the object itself.

That depends. For a reference type, that's correct. For a value type,
you are returning a copy of the object, not a reference to it.

But obviously, I am talking about a reference object here. That was why I
included the class "Response" - so you could see that object1, object2 and
objectPtr reference pointers.
Technically, it's not the "passing back" that prevents the garbage
collection, it's the fact that it's assigned to some variable. If you
just call your method:

BuildData();

without assigning the return value to something, the object returned by
the method as a reference is still garbage collected, even though it was
passed back.


That part I understand. It is not just that I am assigning it, but that the
object has something referencing it that prevents the garbage collection
(which is really what you said).

Thanks,

Tom
 
T

tshad

Peter Duniho said:
[...]
As I mention above, this is the problem. Whether they are locals,
instance
members or static member is really irrellevent to the the question. I
wasn't really concerned with the garbage collection, that was just extra
that I mentioned in my questions as I thought that would make it more
clear
as to what I wanted to figure out.

I don't understand your logic. You say that you omitted things from your
code that would have made the example clear so that you wouldn't have
people responding to things you don't want them responding to, but then
you included things in your question (garbage collection) that you don't
want them responding to, because you "thought that would make it more
clear".

You're right I shouldn't have mentioned the GC. It just came up as I was
putting it together.
Surely as a programmer, you can see the contradiction.
[...] So
after I determine which object I want (object1 or object2), I will make a
couple of more changes to the object and then pass that back to another
calling program - in this case it would be objectPtr.

That doesn't explain why you assign to "objectPtr" _before_ assigning to
one of either "object1" or "object2". But, hey...it's your program. If
you like the extraneous assignment, by all means go ahead. I don't mean
to tell you how to write the program...I'm just trying to figure out if an
anomaly is just that, or some meaningful piece of information in the
question. Sounds like in this case, it's just an anomaly.
Of course not. That was why I changed it and put the assignment afterwords.
If you remember, the point was that I wasn't sure whether the pointer
changed to a new object from BuildData function OR the object itself (from
BuildData) was copied to the object that object1 was originally pointing at.
In the second case, the code would work. But since the reference itself
changes I then moved the assignment AFTER the BuildData. Now it works.
[...]
Based on what you said, I assume that:

When you return an object, you are just returning a reference to that
object
and not actually do anything to the object itself.

That depends. For a reference type, that's correct. For a value type,
you are returning a copy of the object, not a reference to it.

But obviously, I am talking about a reference object here. That was why
I
included the class "Response" - so you could see that object1, object2
and
objectPtr reference pointers.

Your follow-up question wasn't qualified to the code example. You didn't
write "when you return a Response object". So, no...it is NOT obvious
that you are talking about a reference object here.


Not sure what you mean here:

"I am confused on whether pointers are passed or objects are passed on
return
of function where we are returning an object"

Here I am talking about pointers (which you rightly state I should call
references - but references are just pointer type). And as I say "Response"
is a class/object - so if I do:

Response BuildData()

I am passing back a Response object which is a reference object as all
class/objects are reference objects - correct?

Thanks,

Tom
 
T

tshad

Peter Duniho said:
[...]
That doesn't explain why you assign to "objectPtr" _before_ assigning to
one of either "object1" or "object2". But, hey...it's your program. If
you like the extraneous assignment, by all means go ahead. I don't mean
to tell you how to write the program...I'm just trying to figure out if
an
anomaly is just that, or some meaningful piece of information in the
question. Sounds like in this case, it's just an anomaly.
Of course not. That was why I changed it and put the assignment
afterwords.

No. The new code has the assignment to "objectPtr" first. As in:

objectPtr = BuildData();
object1 = objectPtr;

objectPtr = BuildData();
object2 = objectPtr;

Actually, I did put the objectPtr afterwords in the new code:

Original code:

class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

objectPtr = object1;
objectPtr = BuildData();

objectPtr = object2;
objectPtr = BuildData();
}

New Code:

class A
{
Response object1 = new Response();
Response object2 = new Response();
Response objectPtr = null;

public void test()
{
objectPtr = BuildData();
object1 = objectPtr;

objectPtr = BuildData();
object2 = objectPtr;
}
}

In the first case I am moving the pointer from object1 to objectPtr
(obviously won't do me any good here). In the 2nd case, I am moving the
objectPtr that I just got from BuildData() to the object1. That is what is
different.

What is the point of using "objectPtr" at all, in the above code? For
sure, the first assignment is completely useless, because the only thing
the variable is used for before it gets a new value is assigning the value
to a variable that could have gotten the value directly from the method
call.

I agree with you here that this won't do much - but doesn't hurt anything.
Actually, in the code objectPtr is a global variable and I only do:

BuildData();
object1=objectPtr;

Where objectPtr would be set inside of BuildData(). Was just trying to show
that BuildData() set it and then I moved it to object1 or object2.
Why not just write:

object1 = BuildData();
object2 = BuildData();

I could have, but as mentioned objectPtr is global and being set inside
BuildData().
I don't see any meaningful purpose is including "objectPtr" in the code,
thus I classify it as an anomaly.
[...]
But obviously, I am talking about a reference object here. That was
why I
included the class "Response" - so you could see that object1, object2
and
objectPtr reference pointers.

Your follow-up question wasn't qualified to the code example. You
didn't
write "when you return a Response object". So, no...it is NOT obvious
that you are talking about a reference object here.

Not sure what you mean here:

"I am confused on whether pointers are passed or objects are passed on
return
of function where we are returning an object"

That's not the text to which I was replying. I answered this much more
general statement:

Based on what you said, I assume that:

When you return an object, you are just
returning a reference to that object and
not actually do anything to the object
itself.

You wrote "an object". Not "a Reponse object". Lacking context, I felt
it important to point out the difference.
Here I am talking about pointers (which you rightly state I should call
references - but references are just pointer type).

References are _not_ "just pointer type". In particular, while the
current implementation is in fact essentially a pointer, there's nothing
to guarantee that. As far as a C# programmer should be concerned, a
reference is a unique data type entirely different from a pointer. That's
why C# has references _and_ pointers.
And as I say "Response"
is a class/object - so if I do:

Response BuildData()

I am passing back a Response object which is a reference object as all
class/objects are reference objects - correct?

All classes are reference types. Not all objects are reference types.
Some are value types.

But if you create an object/class, would that not be a reference type as I
did?

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top