473,395 Members | 1,568 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Can I modify pointer to an Object which is passed into a class?

TZ
I have two classes, UIHousehold and WIZEditHousehold (both are
winforms).

UIHousehold creates and shows the WIZEditHousehold (WIZEditHousehold
can't be modal, so UIHousehold doesn't know when WIZEditHousehold
closes).

A reference to a buffer within UIHousehold is supplied (passed by REF)
to the constructor of WIZEditHousehold - that constructor saves the
reference to the buffer in a member variable.

OnClose, the WIZEditHousehold attempts to change the reference to the
buffer. That change is not working (the changes are never seen in
UIHousehold).

Here's pseudocode:

class WIZEditHousehold
{
BufferClass _fromUIHousehold;
BufferClass _changedInWizard;
WIZEditHousehold(ref BufferClass bufferFromUIHousehold)
{
_fromUIHousehold = bufferFromUIHousehold;
}

OnClose()
{
_fromUIHousehold = _changedInWizard;
}
}

OnClose, _fromUIHousehold values change in WIZEditHousehold, but these
values are NOT changed in UIHousehold's instance of BufferClass.

In summary, my problem is that I want to change the BUFFER POINTER, but
C# is treating _fromUIHousehold as a Pass By Value reference, not a
true reference (modifiable pointer).

I can accomplish this task via interfaces, upgrading BufferClass, or
events, but my proposed solution is much easier to code for the
multitudes of wizards and buffers I'm developing. Are there any ways
to allow me to treat _fromUIHousehold as a modifiable pointer to
UIHousehold's buffer?

Nov 16 '05 #1
6 1497
Yes, this code snipped will display exactly the behaviour you describe.
Here's a blow-by-blow.

BufferClass _fromUIHousehold;
BufferClass _changedInWizard;
WIZEditHousehold(ref BufferClass bufferFromUIHousehold)
{
_fromUIHousehold = bufferFromUIHousehold;
}

Let's say, for the sake of argument, that the storage for the
BufferClass object is at location 0xbcbc in memory, and that the memory
for the reference to the buffer, which forms part of UIHousehold, is at
location 0xefef.

When you call WIZEditHousehold, the argument value on the stack will be
0xefef... a reference to the location where the point to the
BufferClass object (0xbcbc) is stored.

Then you will copy the reference to the BufferClass object into a
private member called _fromUIHousehold. So, you follow the pointer on
the stack to location 0xefef, and copy what's there, 0xbcbc, into
_fromUIHousehold. Now your WIZEditHousehold constructor exits. At this
point, WIZEditHousehold has lost track of the location of the
BufferClass reference pointer (0xefef). All it has, in the local,
private member _fromUIHousehold, is the address of the BufferClass
object itself, 0xbcbc.

Now, when you close the form, you do this:

OnClose()
{
_fromUIHousehold = _changedInWizard;
}

So, you assign a reference to some other BufferClass object to the
_fromUIHousehold member. However, the form is about to be disposed, so
the assignment does very little.

The source of your confusion is this: bufferFromUIHousehold is a
reference item. If you say

bufferFromUIHousehold = xxxx;

then the object reference back in UIHousehold will change. However,

_fromUIHousehold

is just a normal object reference like any other. Just because you
assigned to it from a "ref" parameter doesn't make it magically become
a reference to a reference: the "ref" parameter is _dereferenced_
during the assignment, so that a reference to a BufferClass ends up in
_fromUIHousehold, not a reference to a reference to a BufferClass,
which is as it should be.

In fact, there's really no way, using safe C#, to do what you want to
do: store a reference to a reference away and then use it later.

Fortunately, there's a way to get the effect you want, even if the
mechanism is different: use events. UIHousehold subscribe to
WIZEditHousehold's "Closing" event. When the ..._Closing() event
handler in UIHousehold is called, do this:

private void WIZEdit_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
WIZEditHousehold wiz = (WIZEditHousehold)sender;
this.myBuffer = wiz.Buffer;
}

then make a "Buffer" property in WIZEditHousehold that allows
UIHousehold to get its buffer whenever it wants (in this case, when the
form is closing).

Nov 16 '05 #2
TZ
Bruce,

Thanks for the explanation of what's going on behind the scenes.

Since C# doesn't really allow me to use modifiable pointers, I think
I'll use an interface. Events would work, but are more problematic
from a maintenance standpoint - if another class ever needed to use
WIZEditHousehold, the developer would need to know to subscribe to the
event. If instead I have a single constuctor to WIZEditHousehold which
takes an IHouseholdContainer, all future users of WIZEditHousehold
could not create the wizard without supplying the interface.

OnClose will use the IHouseholdContainer.SetHouseholdInfo to change the
caller's Household.

By the way, my orginal design used Interfaces, then I thought of this
much more elegant solution. More elegant, but WRONG! :)

Nov 16 '05 #3
"Bruce Wood" <br*******@canada.com> a écrit dans le message de news:
11*********************@o13g2000cwo.googlegroups.c om...
In fact, there's really no way, using safe C#, to do what you want to
do: store a reference to a reference away and then use it later.


Oh but there is :-))

Start off by creating a class that can hold a reference to a field. Or
rather it needs to hold a reference to both the field and the object that
holds the field :

///////////////////////////
class RefHolder
{
object fieldOwner = null;

FieldInfo fi = null;

public RefHolder(object fieldOwner, string fieldname)
{
//assume we are getting a field, but this could use PropertyInfo
instead
Type t = fieldOwner.GetType();
fi = t.GetField(fieldname, BindingFlags.Instance |
BindingFlags.NonPublic);
this.fieldOwner = fieldOwner;
}

public object Field
{
get { return fi.GetValue(fieldOwner); }
set { fi.SetValue(fieldOwner, value); }
}
}

Next create your Buffer class :

class TestBuffer
{
private string name;

public TestBuffer(string name)
{
this.name = name;
}

public string Name
{
get { return name; }
}
}

Now create your class that holds the original buffer and that is going to
create the WIZEdit :

class UIHousehold
{
// set up a buffer
private TestBuffer test = new TestBuffer("Joanna");

public void CreateWIZEdit()
{
// create a RefHolder for your buffer by passing 'this' plus name of
field that holds buffer
RefHolder rh = new RefHolder(this, "test");

// create WIZEdit passing ref to buffer
WIZEditHousehold weh = new WIZEditHousehold(rh);

// simulate closing the form; this would normally be called from
inside the WIZEdit
weh.ChangeBuffer();
}

// provide a property so that we can see the old/new values of the
'buffer'
public string BufferContents
{
get { return test.Name; }
}
}

Here is the WIZEdit 'form' that is passed a 'buffer' and will change the
buffer when it closes

class WIZEditHousehold
{
private RefHolder buffer = null;

public object Buffer
{
get { return buffer.Field; }
set { buffer.Field = value; }
}

public WIZEditHousehold(RefHolder buffer)
{
this.buffer = buffer;
}

// method to simulate form closing
public void ChangeBuffer()
{
Buffer = new TestBuffer("TZ");
}
}

Finally , a quick test program :

class Program
{
static void Main(string[] args)
{
UIHousehold uih = new UIHousehold();

Console.WriteLine(uih.BufferContents);

uih.CreateWIZEdit();

Console.WriteLine(uih.BufferContents);
}
}
//////////////////////////////////

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #4
"TZ" <to*@travelerz.net> a écrit dans le message de news:
11*********************@g14g2000cwa.googlegroups.c om...
By the way, my orginal design used Interfaces, then I thought of this
much more elegant solution. More elegant, but WRONG! :)


Not totally; see my post replying to Bruce :-))

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #5
Very clever. However, isn't this a rather long row to hoe for
inter-form communication? (A good thing to keep in the tookit, though,
for other situations. :)

Correct me if I'm wrong (as you've seen, I often am :), but the usual
paradigm for communication between Forms in .NET is events. TZ, other
developers will be expecting to see your forms sending events to each
other to notify each other that important things have happened (such as
closing, the user doing some action, etc.) This is the standard method
of communication within WinForms applications.

I would hesistate to come up with a whole new way of solving the
problem of communicating a result from a form... just because other
developers trying to use your class will wonder why you just didn't do
it the "usual way", and will have to spend that bit of extra time
trying to figure out how your way works. The "usual way," to my
understanding, is that forms expose properties from which anyone else
can read important information about the form (including anything the
user may have indicated by his/her actions). Then, the form either:

1. Simply returns, if invoked by ShowDialog(). The calling object then
fetches results from properties of the form before calling its
Dispose() method.
2. Relies on interested parties to subscribe to the Closing event, and
fetch results from properties of the form before it closes and disposes
itself.

On the contrary, I find your method of passing information to the
constructor so that the form can store its result in an outside object
to be problematic in other ways (not just because it's "not the usual
way"). What if two outside objects want to know what the user did?
Right now, they can both just subscribe to Closing and poll the
property when their event handlers are called.

Nov 16 '05 #6
"Bruce Wood" <br*******@canada.com> a écrit dans le message de news:
11*********************@c13g2000cwb.googlegroups.c om...
Very clever. However, isn't this a rather long row to hoe for
inter-form communication? (A good thing to keep in the tookit, though,
for other situations. :)
Yes, the end result is certainly the wrong way to do things; I just took up
the challenge of achieving the means to the end :-))

I will write this up in an article and put it on my blog. Does anyone have a
good legitimate scenario where this would come in useful?
Correct me if I'm wrong (as you've seen, I often am :), but the usual
paradigm for communication between Forms in .NET is events. TZ, other
developers will be expecting to see your forms sending events to each
other to notify each other that important things have happened (such as
closing, the user doing some action, etc.) This is the standard method
of communication within WinForms applications.


<snip>

Your comments are correct and very useful and I hope that TZ takes note and
modifies his model.

Joanna

--
Joanna Carter
Consultant Software Engineer
Nov 16 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: lawrence | last post by:
I had some code that worked fine for several weeks, and then yesterday it stopped working. I'm not sure what I did. Nor can I make out why it isn't working. I'm running a query that should return 3...
3
by: jimjim | last post by:
Hello, My question concerns as to how a pointer is passed by reference as a function argument. The following is from code taken from the MICO implementation of the CORBA specification. in...
4
by: Markus Dehmann | last post by:
I guess this is a kind of newbie question (since most pointer questions are newbie questions). In the program below, modify(string* s) is supposed to change the content that s points to. But the...
5
by: Kurt Lange | last post by:
How to I dereference a pointer to an object. I say dereference, because I don't now how to better explain this.... function firstFunction(byval obj as class1) as class1 dim returnVal as...
29
by: shuisheng | last post by:
Dear All, The problem of choosing pointer or reference is always confusing me. Would you please give me some suggestion on it. I appreciate your kind help. For example, I'd like to convert a...
6
by: Kiran | last post by:
Hi all, What I am trying to do is to pass a pointer to the first element of an array to a function, modify it in that function, and then print out the values of the array (which has been modified...
5
by: StephQ | last post by:
This is from a thread that I posted on another forum some days ago. I didn't get any response, so I'm proposing it in this ng in hope of better luck :) The standard explanation is that pointer...
5
by: Tim Frink | last post by:
Hi, I'm experimenting with function pointers and found two questions. Let's assume this code: 1 #include <iostream> 2 class A; 3 4 //////////////////////////////////////////// 5 class B
50
by: Juha Nieminen | last post by:
I asked a long time ago in this group how to make a smart pointer which works with incomplete types. I got this answer (only relevant parts included): ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.