views:

364

answers:

7

Variables, methods and classes can receive various security levels. From my C# experience, there is:

public
internal
protected
protected internal
private

Now, I understand the use of making methods and classes private, or internal or protected, but what about variables? Even if I make a variable private, I can use a Property to call it from a different class.

I've always been thought that Properties are best-practice. So if I can use that, I don't need to call variables directly via an Instance.

Is there any reason not to make a variable private?

EDIT: I see some people talking about Properties as if they are nothing more than Glorified public variables

Quick reminder: public variables return just their value. With properties, you can do more. For instance:

public int AmountOfBooks{
  get {
    //code to check certain conditions
    //maybe trigger an event while we're at it.
    //and a few conditionals.
    return this.amountOfBooks;
  }

  set {
    //a few conditionals
    //maybe trigger an event
    this.amountOfBooks = value;
    //and I can do even more... I think, never tried this.
  }
}

Those of you who've read my profile know I'm a student. Using properties as "glorified public variables" is something I see a lot of fellow students do. The most common response when telling them they can do this is: "Is that allowed?"

+12  A: 

Sure, there are situations in which it makes sense to have a public field. For example, if you are creating a struct solely for interoperability with an existing unmanaged win32 API.

But if you are building a regular managed object model, the best practice is to model the properties of your objects as properties, and use fields as the mechanism that privately implements the publically exposed functionality.

UPDATE: I'll take this opportunity to note that we have tried to make it very easy in C# 3.0 to write a property which simply accesses a backing store:

public int Foo { get; set; }

is exactly the same as

private int _Foo;
public int Foo { get { return _Foo; } set { _Foo = value; } }

but a lot shorter and easier to read. And of course if you need to expand it into the long form with a backing store later, doing so is not a breaking change.

You can also do this:

public int Foo { get; private set; }

if you want to make a property that is read-only to code outside the class/struct.

Eric Lippert
Can you elaborate on why you feel this is the best practice, particularly for properties which merely copy their value to a private instance member?
Jed Smith
You do this to be able to change the implementation of the property without affecting consumers.
Alex
(1) changing a field to a property in the future is a breaking change. (2) properties are for modeling the *properties* of an object. Hence the name. Suppose you're modeling a car. Is color a *property* of a car? Have you ever heard anyone say that color is a *field* of a car? Of course not. Make the choice that reflects the thing you are modeling; model properties of a thing with properties.
Eric Lippert
Thank you for the clarification -- I wasn't aware field -> property is a breaking change in .NET; as Alex Martelli points out, it's because I live in Pythonland.
Jed Smith
+1 for "not a breaking change". This is the key point.
Greg D
What Greg D said.
David Thornley
A: 

for example, if you had a class with attribute id_code.

if the attribute is public I can set this variable with any type of value.

if you delcare this id_code private and you make a method for set it, you can make a rules about the format of id_code. And so the method:

public setIdCode(String id) {
    my_attribute_id_code = "000"+id;
}

this is a first simple example.

tommaso
+4  A: 

Off the top of my head, I can think of two places where I would use public fields

  1. to publish constant or read-only values for consumers of an assembly
  2. where I am forced to by parts of the infrastructure (e.g in Workflow Foundation)
Steve Gilham
+1 - I was just writing about the readonly and const keywords as being a reason.
James Black
A: 

Yes. For example, marking a field as protected allows it to be used directly by a derived class which still conceptually maintaining the object-oriented philosophy.

In general, though, you are correct. It is generally preferred to mark fields of a class as private and expose the necessary ones as properties. This facilitates things such as encapsulation, field validation, and code maintenance.

Matt Davis
A: 

If your property say Status is of the nature:
public int Status {get; set;}

Some people might just use:
public int Status;

o.k.w
+1 -- And they shouldn't be afraid to. It's like the `goto` keyword, in a way.
Jed Smith
+7  A: 

Properties are a best practice if there is any code you need to execute when the variable is set or gotten -- or if there is any incompatible-change in API involved should you ever need to add such code in the future.

Due to the latter clause, it most likely does make sense to use accessors "preemptively" in language that would otherwise require such incompatible changes (the best known example being the getThis/setThis convention in Java)!

But when your language lets you switch from public variables to properties and vice-versa without any incompatible change in the API (such as C#, Ruby, Python, ...), it's silly to carry around total boilerplate when the public accessors (getter and setter) do nothing except copying to and from a private variable -- even if you're certain your compiler can optimize them away, such boilerplate accessors just bloat the source uselessly, and waste an important design feature that's part of what makes such languages nice ones;-)

Alex Martelli
Changing a variable to a property is an incompatible change in C#. Sure the syntax is the same but it requires recompilation of the client code.
Esben Skov Pedersen
It's a change, but not an _incompatible_ change -- VS will smoothly and intrinsically deal with rebuilding the assembly, no code change required (so, no manual action on the programmer's part). (Changes _across_ assembly boundaries are not quite as obvious wins;-).
Alex Martelli
A: 

There are situations where fields are treated differently than properties. The standard serialization formatters (BinaryFormatter and SoapFormatter) will serialize fields, but not properties. There may be times where this is necessary to control the serialization of your type.

CodeSavvyGeek