Get/Set vs Public Variables

J

JB

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?
 
J

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#.
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
 
M

Marc Gravell

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
 
M

Marc Gravell

Oh, also, you can't use fields to implement interfaces - only
properties, methods, etc

Marc
 
M

Marc Gravell

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
 
B

BlackWasp

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.
 
M

Marc Gravell

 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
 
P

Paul Werkowitz

Am Mon, 4 Feb 2008 05:54:37 -0800 (PST) schrieb Jon Skeet [C# MVP]:
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
 
J

Jon Skeet [C# MVP]

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.
 
S

Scott Roberts

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

class Person
{
string name;
string firstname;
}

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.
 
R

Rene

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.


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.
 
R

Rene

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.


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.
 
P

Paul Werkowitz

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
 
J

Jon Skeet [C# MVP]

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....

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
 
P

Paul Werkowitz

Am Tue, 5 Feb 2008 15:44:16 -0600 schrieb Scott Roberts:
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
 
P

Paul Werkowitz

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
 
S

Scott Roberts

Paul Werkowitz said:
Am Tue, 5 Feb 2008 15:44:16 -0600 schrieb Scott Roberts:


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.

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.
 
S

Scott Roberts

Paul Werkowitz said:
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.

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?
 
B

Ben Voigt [C++ MVP]

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
 
R

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.

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.



Paul Werkowitz said:
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
 

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