Passing a class containing reference type fields as a parameter problem.

R

Ross McLean

Hi all,
I've been teaching myself C# for a new project at work. I have a bit of
a background in c++ and java but never been what you could call a guru.

I'm having some strange things happening when I pass a class as a
parameter to a Windows Form. Basically, I have a class that has several
fields, two of these fields are an instance of an inner class, the rest
are basic value types (bool's in this case). I have a windows form, the
constructor takes one parameter(my class) which I then use to initialise
the controls on the form.

Now, am right in saying since my class is a reference type by default it
is passed as a reference, so any changes on the parameter by the forms
code is reflected in the calling function? This generally is what I see
happening, however I am loosing reference to my properties that are
themselves classes.

Here's a cut down version of my class:

public class PrintListConfiguration
{
public class HeaderFooterConfiguration {
public bool PerPage;
public bool Title;
public bool Criteria;
public bool Date;
public bool Pages;

#region constructors
...
#endregion
}

public bool Borders;
public bool StatusColumn;
public bool RowNumbers;
public HeaderFooterConfiguration Header;
public HeaderFooterConfiguration Footer;

#region Constructors
...
#endregion
}

As you see it has two reference fields Header and Footer.

I create a new instance of a form passing in an instance of the class as
the parameter.

PrintList printList = InitialisePrintList();
PrintListForm printListsForm = new PrintListForm(printList);

Then, in my forms constructor I set the state of the controls based on
my class I passed in.

public PrintListForm(PrintListConfiguration printList) {
InitializeComponent();
cbBorders.Checked = printList.Borders;
cbRowNumbers.Checked = printList.RowNumbers;
cbStatusColumn.Checked = printList.StatusColumn;

//cbHeader.Checked = printList.Header == null ? false : true;
//cbFooter.Checked = printList.Footer == null ? false : true;

if (printList.Header != null) {
cbHeaderDate.Checked = printList.Header.Date;
cbHeaderPages.Checked = printList.Header.Pages;
cbHeaderPerPage.Checked = printList.Header.PerPage;
cbHeaderSearchCriteria.Checked = printList.Header.Criteria;
cbHeaderTitle.Checked = printList.Header.Title;
}
if (printList.Footer != null) {
cbFooterCriteria.Checked = printList.Footer.Criteria;
cbFooterDate.Checked = printList.Footer.Date;
cbFooterPages.Checked = printList.Footer.Pages;
cbFooterPerPage.Checked = printList.Footer.PerPage;
cbFooterTitle.Checked = printList.Footer.Title;
}
}

Now, my problem:
I've commented out two tests on the classes reference fields header and
footer. It should test to see if they are null and set a checkbox state
based on that test.
If I include that test the header and footer types are lost (they just
include 5 bool values that all get reset to false). Tracing through the
code they only get set to false at that exact lines, before those lines
they contain the values passed in by the calling function.
If I move those lines to the bottom of the function then it works fine,
my forms control states are set correctly based on the passed in class.

Does anyone know what is causing this behaviour? Is there some form of
garbage collection taking place? I tried suppressing the GC but didn't
see any difference. I may have done something wrong there though as I
never persevered down that path.

I'm sure there is various other options that would result in me not
having to do what I'm doing, but now that I've gotten this far I really
what to know what's happening to my instance of my class!

Thanks in advance,
Ross McLean
 
J

Jon Skeet [C# MVP]

Ross said:
I've been teaching myself C# for a new project at work. I have a bit of
a background in c++ and java but never been what you could call a guru.

I'm having some strange things happening when I pass a class as a
parameter to a Windows Form. Basically, I have a class that has several
fields, two of these fields are an instance of an inner class, the rest
are basic value types (bool's in this case). I have a windows form, the
constructor takes one parameter(my class) which I then use to initialise
the controls on the form.

Now, am right in saying since my class is a reference type by default it
is passed as a reference, so any changes on the parameter by the forms
code is reflected in the calling function? This generally is what I see
happening, however I am loosing reference to my properties that are
themselves classes.

That's correct. Unfortunately, you haven't shown us enough code to see
what's going wrong. In particular, you haven't shown the constructors
which are meant to set the header and footer information.

Could you post a short but complete program that demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.

(Just a slight aside - you haven't currently got properties, you've got
fields which are public. That's generally not a good idea - it's better
to expose a public property which has an underlying private field
backing it.)

Jon
 
R

Ross McLean

Jon said:
That's correct. Unfortunately, you haven't shown us enough code to see
what's going wrong. In particular, you haven't shown the constructors
which are meant to set the header and footer information.

Could you post a short but complete program that demonstrates the
problem?

See http://www.pobox.com/~skeet/csharp/complete.html for what I mean by
that.

Thanks for the reply Jon. I'll constructor a working simplified working
sample and post.

I'd removed the constructors as in this instance the object is being
serialized using the XmlSerailizer so there I didn't bother showing it.
(Just a slight aside - you haven't currently got properties, you've got
fields which are public. That's generally not a good idea - it's better
to expose a public property which has an underlying private field
backing it.)

Yep, absolutely correct, I do have fields, not properties. At the time
of creating pecific class I was playing with XmlSerialiser and didn't
know that if it would serialise public properties.
 
R

Ross McLean

Thanks for the reply Jon. I'll construct simplified working
sample and post.

Well in creating a simplified version of my code I can't recreate the
problem! It does however give me some further avenues to explore.
The sample program did not involve any Forms, just straight method
parameter passing, and worked as I expected.
I'm running Vis Studio 2005 Beta .Net Framework 2.0 so I will retry my
actual code where possible using .Net 1.1.

Thanks,
Ross McLean
 

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