Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / C# / March 2008

Tip: Looking for answers? Try searching our database.

Get/Set vs Public Variables

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
JB - 04 Feb 2008 13:48 GMT
I was always taught in C++ that using public variables was a bad idea,
which i could understand, so some generic get/set methods were usually
wrote to access the data.

Now in C# I'm just curious about properties.

Say I have

class SomeClass
{
private in data
public int Data()
{
get {return data;}
set {data=value;}
}

vs

class SomeClass
{
public int data
}

Most seem to prefer using the properties approach, but not yet being a
pro at C# i'm struggling to find a difference.
In effect they both seem exactly the same.
I can see how using properties would be useful if you need to apply
some sort of extra processing before setting the value, or for
creating read-only/write-only variables.

But for the very basic, is there any reason i should be using
properties instead of public variables?
In fact for the basic is there any difference in execution time
between get/set and direct access?
Jon Skeet [C# MVP] - 04 Feb 2008 13:54 GMT
> I was always taught in C++ that using public variables was a bad idea,
> which i could understand, so some generic get/set methods were usually
> wrote to access the data.

It's exactly the same in C#. I don't really see how you can understand
why it's a good thing in C++, but not in C#.

> Most seem to prefer using the properties approach, but not yet being a
> pro at C# i'm struggling to find a difference.
> In effect they both seem exactly the same.

No, they don't. Exposing the fields is exposing the *implementation* -
how the data is stored. Exposing the properties just says "I have this
state, but you're not allowed to know how it's stored".

The underlying storage shouldn't be part of the public API - the fact
that data *is* stored (or computed, or generally made available) *is*
part of the public API.

> But for the very basic, is there any reason i should be using
> properties instead of public variables?

Yes - to avoid exposing the implementation.

> In fact for the basic is there any difference in execution time
> between get/set and direct access?

Not after JIT inlining.

Jon
Paul Werkowitz - 05 Feb 2008 21:14 GMT
Am Mon, 4 Feb 2008 05:54:37 -0800 (PST) schrieb Jon Skeet [C# MVP]:

>> I was always taught in C++ that using public variables was a bad idea,
>> which i could understand, so some generic get/set methods were usually
>> wrote to access the data.
>
> It's exactly the same in C#. I don't really see how you can understand
> why it's a good thing in C++, but not in C#.

First, more tahn 90% of properties I saw in my life are simple setters and
getters without any useful functionality.

Second, chances are really low that a construct like

class Person
{
  string name;
  string firstname;
}

EVER will need any functionality in getters and setters for the two string
fields.

So, why is it a bad idea to expose them directly to clients?

- dirty management for business objects? No. This requires to explicitely
call some function (IPropertyChanged) in the setter, only for that purpose.
There are better ways.

- Binding to external code? No. When someone ref-binds to a public variable
and this is later changed to a property, we must change the statement and
recompile. Big deal? IMO, no.

- Databinding etc? No. It is a conceptual lack of WinForms (and WPF)
databinding that it can bind only to properties and not to variables.
Technicaly, it is no problem to include variables in binding. But LINQ
alleviates most of that.

Of course, there are situations where this is sinply wrong. If I must
anticipate the situation that my implementation might change, I definitely
am better off with properties. But for > 90% of all classes with data
members this is NOT the case. And if I make a mistake here, the cost is low
- mostly recompilation, and some syntax errors. Definitely not worth to
make everything private.... - at least until auto-properties were invented.

Greetz
Paule
Jon Skeet [C# MVP] - 05 Feb 2008 21:20 GMT
<snip>

> Of course, there are situations where this is sinply wrong. If I must
> anticipate the situation that my implementation might change, I definitely
> am better off with properties. But for > 90% of all classes with data
> members this is NOT the case. And if I make a mistake here, the cost is low
> - mostly recompilation, and some syntax errors. Definitely not worth to
> make everything private.... - at least until auto-properties were invented.

If you want to ignore best practice, that's your call. I'll stick to
exposing an API which doesn't expose the implementation.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Paul Werkowitz - 06 Feb 2008 15:15 GMT
Am Tue, 5 Feb 2008 21:20:43 -0000 schrieb Jon Skeet [C# MVP]:

> If you want to ignore best practice, that's your call.

Of course. At least until someone can show arguments why "always use
properties and make data private" is "best practice".

I gave some arguments why IMO this is not so, but until now you did not
give any reasoning.

Looking forward to hearing....

Greetz
Paule
Jon Skeet [C# MVP] - 06 Feb 2008 15:23 GMT
> > If you want to ignore best practice, that's your call.
>
[quoted text clipped - 5 lines]
>
> Looking forward to hearing....

Well, you've already dismissed the important reasons as being
unimportant to you:
1) Discriminating between implementation and API
2) Binary compatibility of old code running against new implementation
3) Source compatibility of old code compiling against new
implementation

Those are all good enough reasons for me, but apparently not enough
for you.

In my experience that's okay if you're just messing around or never
see multiple versions of the same code - but doesn't work in most
commercial environments.

Jon
Paul Werkowitz - 09 Feb 2008 16:02 GMT
Am Wed, 6 Feb 2008 07:23:00 -0800 (PST) schrieb Jon Skeet [C# MVP]:

> Well, you've already dismissed the important reasons as being
> unimportant to you:
> 1) Discriminating between implementation and API
> 2) Binary compatibility of old code running against new implementation
> 3) Source compatibility of old code compiling against new
> implementation

and, not to forget the new dependency properties etc. of WPF, to add to the
list.

If these reasons are important (or only one of them, mainly the first) -
yes, then we should use properties. But: for most objects, these
requirements are not si important. More than 90% of the property
implementations I have seen are simple setters and getters without any
functionality, and never will need any. I still have the opinion that these
are superfluous things.

I agree that there are situations where they are useful, or even necessary.
You named some.

At the moment, if I want to use databinding for example, I have to use
properties on my business object. The properties are all empty, because my
validation etc. is done otherwise. (Most of it could not be done in setters
anyway, because validity of one data element heavily depends on other data
elements in the same object). Fortunately, this is alleviated with the
auto-property feature of .NET 3

> Those are all good enough reasons for me, but apparently not enough
> for you.

So, you access all of your data in every object of ll your applications
only via properties. OK - and how many of theses properties are really
empty? And will probably stay empty during the lifetime of the product?

Greetz
Paule
Jon Skeet [C# MVP] - 09 Feb 2008 19:09 GMT
<snip>

> > Those are all good enough reasons for me, but apparently not enough
> > for you.
>
> So, you access all of your data in every object of ll your applications
> only via properties. OK - and how many of theses properties are really
> empty? And will probably stay empty during the lifetime of the product?

Many - but I don't need to worry about binary or source
incompatibilities if I *do* need to do anything. Where's the harm?
Writing a property takes seconds with appropriate templates etc. The
only real downside IMO is that the code is then there, potentially
being obtrusive in your class. That's reasonably easily solved with
regions.

With C# 3 there's even less reason not to use properties, as automatic
properties let you follow best practices with just a single line of
code.

Signature

Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet   Blog: http://www.msmvps.com/jon.skeet
World class .NET training in the UK: http://iterativetraining.co.uk

Scott Roberts - 05 Feb 2008 21:44 GMT
> First, more tahn 90% of properties I saw in my life are simple setters and
> getters without any useful functionality.

Hmmm, I've not had the same experience.

> Second, chances are really low that a construct like
>
[quoted text clipped - 6 lines]
> EVER will need any functionality in getters and setters for the two string
> fields.

So "name" and "firstname" can hold an unlimited number of characters? I
guess that's fine if you don't use a DB or your DB fields allow unlimited
characters. In practice, most strings have a maximum size. I guess you could
validate it later (like before saving) but I personally prefer to avoid
invalid states rather than report invalid states.
Paul Werkowitz - 06 Feb 2008 15:24 GMT
Am Tue, 5 Feb 2008 15:44:16 -0600 schrieb Scott Roberts:

>> Second, chances are really low that a construct like
>>
[quoted text clipped - 8 lines]
>
> So "name" and "firstname" can hold an unlimited number of characters?

No, of course not. But it is the responsibility of the data provider to
ensure the condition. The setter can only throw an exception .... a thing
to avoid, frankly.

It is better to have the data provider ensure proper data states. For
example, if the data comes from a GUI, it would be better to implement the
length check in the Edit-Field, and alert the user that no more chars can
be input.

Conclusion: Information about data validity (data model) are needed in
several placed, e.g. in the GUI, sometimes in the DAL etc. But not in the
Person class.

[snip]
> In practice, most strings have a maximum size. I guess you could
> validate it later

No! Definitely not! "Later" would be far too late! I do not wand my clients
to comeplete pages of data and when they press Save, give an error
message...

Greetz
Paule
Scott Roberts - 06 Feb 2008 15:39 GMT
> Am Tue, 5 Feb 2008 15:44:16 -0600 schrieb Scott Roberts:
>
[quoted text clipped - 15 lines]
> ensure the condition. The setter can only throw an exception .... a thing
> to avoid, frankly.

I disagree. The business object should enforce business logic. The maximum
length of of a field, required values, range checks, etc. are all business
rules. Does the data provider arbitrarily decide the max length of a field?
No, it's based on a business rule - which should obviously go in the
business layer.

> It is better to have the data provider ensure proper data states. For
> example, if the data comes from a GUI, it would be better to implement the
> length check in the Edit-Field, and alert the user that no more chars can
> be input.

GUI validation is worthwhile, but it doesn't absolve the business object
from the responsibility of ensuring valid data. If you rely on the "data
provider" to ensure proper data states then you are spreading your business
logic all over the place. Some will exist in the web GUI, some will exist in
the Windows Forms GUI, some in a web service (that allows an API into the
Person class), etc. This is exactly the type of thing that having a business
layer is supposed to eliminate.

> Conclusion: Information about data validity (data model) are needed in
> several placed, e.g. in the GUI, sometimes in the DAL etc. But not in the
> Person class.

Sorry, but the Person class is really the *only* place that it is needed. If
you put it there then you *don't* need it anywhere else (unless you want to
put some simple validation in the GUI for user convenience). If you don't do
any validation in the business layer, then why even have a business layer?
Just forgo the Person class and plug data directly from your GUI into the
database.

> No! Definitely not! "Later" would be far too late! I do not wand my
> clients
> to comeplete pages of data and when they press Save, give an error
> message...

I agree.
Paul Werkowitz - 09 Feb 2008 16:13 GMT
Am Wed, 6 Feb 2008 09:39:55 -0600 schrieb Scott Roberts:

>>> So "name" and "firstname" can hold an unlimited number of characters?
>>
[quoted text clipped - 3 lines]
>
> I disagree. The business object should enforce business logic.

Of course it should! But we were talking about properties (of the BO).
Thats a different thing.

Validity definitions must be near the business data, and be accessable by
all agents that can change business data. So the rules should be in some
form accesible by the program. MS Application Building Block (or so, forgot
the name) for example, uses C#-attributes to specify validation rules.

In WPF, validation logic can be specified with the binding.

But never in setters of the business object!

>The maximum
> length of of a field, required values, range checks, etc. are all business
> rules. Does the data provider arbitrarily decide the max length of a field?
> No, it's based on a business rule - which should obviously go in the
> business layer.

Absolutely. But it should not be coded in a setter. That's my point: then U
cannot use it in other places!

> GUI validation is worthwhile, but it doesn't absolve the business object
> from the responsibility of ensuring valid data. If you rely on the "data
> provider" to ensure proper data states then you are spreading your business
> logic all over the place.

I did not say that the validation logic must be placed in the GUI. I said
that the validation  must be performed in the GUI. That is a differnet
thing. Again: The Data and the rules that define validity of that data must
be in one place AND must be accessible from all parties that can modify
that data - e.G. the GUI.

Greetz
Paule
Rene - 05 Feb 2008 23:08 GMT
> Second, chances are really low that a construct like
>
[quoted text clipped - 6 lines]
> EVER will need any functionality in getters and setters for the two string
> fields.

Other than for experimenting, I have never bee able to do something like you
mentioned.

For example, if this was your typical business object, the name and last
name properties  will probably include checking for certain rules such as
making sure that the last name of the person is not blank or does not exceed
the characters allowed on the database.

Then you are probably going to want to add some sort of security checks
where you may want to throw an exception if the user does not have the
permission to change this value.

The list goes on and on. Adding business logic to your getters and setters
in your bussiness objects make your application more dynamic and robust.

Cheers.
Paul Werkowitz - 06 Feb 2008 15:31 GMT
Am Tue, 5 Feb 2008 17:08:34 -0600 schrieb Rene:

[snip]
> making sure that the last name of the person is not blank ....

And then - how can you create such an object, that is empty? E.G. for
binding to controls in a GUI that are empty? The object would be in invalid
state.

Checks like you mentioned are not to be implementesd in BOs.

Greetz
Paule
Scott Roberts - 06 Feb 2008 17:50 GMT
> Am Tue, 5 Feb 2008 17:08:34 -0600 schrieb Rene:
>
[quoted text clipped - 5 lines]
> invalid
> state.

Well, the setter is obviously not called when the object is created. If the
GUI tried to put a blank value into the property an exception would occur,
which is exactly what should happen.

> Checks like you mentioned are not to be implementesd in BOs.

If you don't put business rules in your BOs, then what *do* you put in
there?
Ben Voigt [C++ MVP] - 06 Feb 2008 23:02 GMT
>> Checks like you mentioned are not to be implementesd in BOs.
>
> If you don't put business rules in your BOs, then what *do* you put in
> there?

public fields, are apparently what Paul puts in there
Paul Werkowitz - 09 Feb 2008 16:19 GMT
Am Wed, 6 Feb 2008 11:50:10 -0600 schrieb Scott Roberts:

>> And then - how can you create such an object, that is empty? E.G. for
>> binding to controls in a GUI that are empty? The object would be in
[quoted text clipped - 4 lines]
> GUI tried to put a blank value into the property an exception would occur,
> which is exactly what should happen.

Right. But if this happens then we have a programming error. GUI must have
acces to validation rules and not allow to put invalid data into a BO.
Instead, GUI should show some info to the user etc...

>> Checks like you mentioned are not to be implementesd in BOs.
>
> If you don't put business rules in your BOs, then what *do* you put in
> there?

Sorry, my wording was wrong. I meant: "... not to be implemented in
setters". Business rules should of course be defined near the BO.

Greetz
Paule
Rene - 07 Feb 2008 21:37 GMT
Paul,

There is nothing wrong with having an object holding an invalid state.
Things don't have to crash. The problem would be if you try to save the
invalid object data to a database for example.

When a new object gets instantiated it could have a collection of broken
rules (one of them being last name can't be blank). When the user set the
value of last name to a valid name you can remove that broken rule, if the
user the set the value to blank again you add the broken rule back again.

The moment the user tries to save the object into the database you can check
the broken rules collection and throw an error if broken rules are found.

Having the business rules right in the getter and setter is a logical place
to have them.

> Am Tue, 5 Feb 2008 17:08:34 -0600 schrieb Rene:
>
[quoted text clipped - 10 lines]
> Greetz
> Paule
Marc Gravell - 07 Feb 2008 22:21 GMT
Just yet another viewpoint...

Validation in the setter is perfect for things that can *never* be
valid, i.e. invalid format, out-of-range, too large, etc. However, it
can get tricky if your business rules cross-reference each other. The
classic example is the DateTimePicker, where Min / Max / Value fight
with eachother; the issue is that you place a dependency on the caller
both setting the right properties *and* setting them in the right
order - which can easily require a 3rd intermediary state.

In such cases, a more explicit Validate() method is useful, but I
agree that this generally belongs to the business entity itself
(unless it is a proxy, in which case all bets are off).

A useful model here is IDataErrorInfo; for starters, if you implement
this it will *automatically* display the messages to the user in some
controls (DataGridView, for example) via an error blob. And it isn't
hard to hook regular bindings to it as well (a bit more manual,
though; and note you need to use the indexer-variant). But more
importantly: it provides a simple method your data-layer can query:

           IDataErrorInfo errObj = obj as IDataErrorInfo;
           string errMsg;
           if(errObj != null && !string.IsNullOrEmpty(errMsg =
errObj.Error)) {
               throw new DataException(errMsg);
           }

Although any similar "are you happy with yourself?" method would
suffice ;-p
(but is nice to be able to use the same code at both UI and DAL,
without having to do anything special)

Marc
Paul Werkowitz - 09 Feb 2008 16:29 GMT
Am Thu, 7 Feb 2008 14:21:29 -0800 (PST) schrieb Marc Gravell:

> Validation in the setter is perfect for things that can *never* be
> valid, i.e. invalid format, out-of-range, too large, etc. However, it
[quoted text clipped - 7 lines]
> agree that this generally belongs to the business entity itself
> (unless it is a proxy, in which case all bets are off).

Full ack.

Paule
Paul Werkowitz - 09 Feb 2008 16:28 GMT
Am Thu, 7 Feb 2008 15:37:32 -0600 schrieb Rene:

> Paul,
>
> There is nothing wrong with having an object holding an invalid state.
> Things don't have to crash. The problem would be if you try to save the
> invalid object data to a database for example.

Or use it in any other context....,  yes!

> When a new object gets instantiated it could have a collection of broken
> rules (one of them being last name can't be blank). When the user set the
[quoted text clipped - 3 lines]
> The moment the user tries to save the object into the database you can check
> the broken rules collection and throw an error if broken rules are found.

That is a very interesting approach, and I use a variation of it for a long
time. I have a isValid-Function that calculates that set of broken rules
(as you named it) on the fly (does not store it). I use that on the GUI for
example to provide users with appropriate feedback (yellow an red markers
near controls, info panel etc.). --- But I don't need no accessors for
that.

> Having the business rules right in the getter and setter is a logical place
> to have them.

Not necessarily. I calculate it on the fly, when needed. Caching is not
necesary, and is more hassle than use. So, down to the bones, I say: I
don't care whats in the object, as long as I can determine its validity
state at any time I need to.

Paule
Rene - 05 Feb 2008 23:08 GMT
> Second, chances are really low that a construct like
>
[quoted text clipped - 6 lines]
> EVER will need any functionality in getters and setters for the two string
> fields.

Other than for experimenting, I have never bee able to do something like you
mentioned.

For example, if this was your typical business object, the name and last
name properties  will probably include checking for certain rules such as
making sure that the last name of the person is not blank or does not exceed
the characters allowed on the database.

Then you are probably going to want to add some sort of security checks
where you may want to throw an exception if the user does not have the
permission to change this value.

The list goes on and on. Adding business logic to your getters and setters
in your bussiness objects make your application more dynamic and robust.

Cheers.
Arne Vajhøj - 10 Mar 2008 02:18 GMT
> First, more tahn 90% of properties I saw in my life are simple setters and
> getters without any useful functionality.
[quoted text clipped - 9 lines]
> EVER will need any functionality in getters and setters for the two string
> fields.

> - Binding to external code? No. When someone ref-binds to a public variable
> and this is later changed to a property, we must change the statement and
> recompile. Big deal? IMO, no.

Not for small programs. But for large scale systems it can be
a huge problem.

Component A and B both uses component C, component A need some
new functionality in C, when that is added B does no longer run
or build, so B has to be changed, and tested, test and delays cost
the company 500000 USD - do you think management consider that
no big deal ?

> Of course, there are situations where this is sinply wrong. If I must
> anticipate the situation that my implementation might change, I definitely
> am better off with properties. But for > 90% of all classes with data
> members this is NOT the case. And if I make a mistake here, the cost is low
> - mostly recompilation, and some syntax errors. Definitely not worth to
> make everything private.... - at least until auto-properties were invented.

Definitely worth doing.

It costs practically nothing. You declare the fields private and let the
IDE generate the public property.

And can save you a ton of problems later.

And yes - it may only be a few percent of properties that will ever
need functionality beyond default.

But the problem is that we do not know what those few percentages
are when we write the code.

Code tend to be used much longer than original intended. 10-25 years
are not unrealistic.

Nobody can guarantee that a given field will not need to be changed
for so long a time span.

Arne
Marc Gravell - 04 Feb 2008 13:57 GMT
> But for the very basic, is there any reason i should be using
> properties instead of public variables?
> In fact for the basic is there any difference in execution time
> between get/set and direct access?

Basically, it just isn't good design:
* You can't change the internals (for instance, to use a facade)
without breaking the clients
* You can't change to properties without it being a breaking change
(esp. if callers have used "ref")
* You can't use validation or virtual
* You can't data-bind to properties (without some work), and can't
raise change notifications

Re performance - for a simple pass-thrue, the JIT should inline it, so
nope.

You'll be glad to hear to C# 3 (in VS 2008) takes away the effort
excuse for not using properties, via auto-implemented properties:

class SomeClass
{
  public int Data {get;set;}
}

there you go! A proper pass-thru property implementation that you can
flesh-out later if you need.

Marc
Marc Gravell - 04 Feb 2008 14:20 GMT
As a random thought... I wonder if (in fantasy future C# wishing land)
there would be any scope for the auto-property setters to declare
partial OnBeforeFooChanged and OnAfterFooChanged methods... maybe even
an OnPropertyChanged for optional INotifyPropertyChanged support - but
I guess that as soon as you open the door even a little bit, it gets
*very* complicated.

Just my random wish-list item for the day (well, OK, my /second/ wish-
list item for today)

Marc
Marc Gravell - 04 Feb 2008 13:58 GMT
Oh, also, you can't use fields to implement interfaces - only
properties, methods, etc

Marc
BlackWasp - 04 Feb 2008 21:52 GMT
In addition to the other useful comments, I have recently been maintaining
that used public variables.  These have been changed to properties as they
caused data-binding problems with the Infragistics WinGrid control.  I would
expect to experience similar issues elsewhere too.

Signature

BlackWasp
www.blackwasp.co.uk

>I was always taught in C++ that using public variables was a bad idea,
> which i could understand, so some generic get/set methods were usually
[quoted text clipped - 31 lines]
> In fact for the basic is there any difference in execution time
> between get/set and direct access?
Marc Gravell - 04 Feb 2008 22:47 GMT
> These have been changed to properties as they
> caused data-binding problems with the Infragistics WinGrid control.

Yes; almost all UI-binding uses TypeDescriptor.GetProperties(), which
only works (normally) with properties. I have seen a
TypeDescriptionProvider implementation that elevates FieldInfo to
PropertyDescriptor, but I wouldn't recommend it...

Marc

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.