views:

669

answers:

8

Doesn't object initialization outside of a constructor break encapsulation ?

Given:

class MyClass 
{  
    public string _aString;  
}

Shouldn't the _aString member be private and instantiated via a call to the constructor (constructor omitted here):

 MyClass test = new MyClass("test");

Instead of the alternate method of object initialization:

MyClass test = new MyClass { _aString = "Test" };
+4  A: 

It is usually considered bad practice to expose public fields... it may be acceptable in some cases, for instance if the field is marked as readonly (which means it must be set in the constructor). Instead, you should make this field private and expose it through a property, which may or may not be readonly, depending on its purpose :

class MyClass
{
    private string _aString;
    public string AString
    {
        get { return _aString; }
        // uncomment to make the property writable
        //set { _aString = value; }
    }
}
Thomas Levesque
A: 

It depends on the purpose of the variable. If the programmer should only be able to set the variable at initialization, but then not have access to it after that, then I would go with the private variable. If you want the class user to be able to set / read the variable at any time, then make it public.

regex
A: 

When you have
public string _aString;
it really does not matter when you initialize this value since this is already exposed. So, when we want to talk about initialization we should move this string into property. Than talkin about encapsutlation makes sense.
So, imagine we have some string. There are mosly two approaches to initializatnion. One is to do it inside constructor, second is lazy initialization (initialize when some request this data).

smok1
A: 

yes, initialize via the constructor, and add properties to allow (or not) access to the data.

class MyClass {
private string _aString;
string MyProperty {
                    get { return this._aString; }
                    // you can make this  private or protected
                    set { this._aString = value; } 

                  }
}
Muad'Dib
+2  A: 

If you consider Properties as getters and setters, I don't believe it will break encapsulation. But you should notice that you didn't use a Property, you have used an instance variable. In fact, I don't believe it will work like your example. Check this one:

class MyClass { private string aString;

public string AString {
    get { return aString; }
    set {aString = value; }
}

} MyClass test = new MyClass { AString = "test" };

In this case, you are accessing the private field through it's accessor. It's just like using a parameterless constructor and setting the value later.

Fernando
Setting public fields directly is a-ok in object initializers (from a language semantics point of view, not proper design).
Pavel Minaev
That I didn't knew! Thanks! =D
Fernando
+4  A: 

"Doesn't object initialization outside of a constructor break encapsulation ?"

Well, no. As you rightly pointed out you can only initialize properties that are already accessible in your current scope. (public, internal etc)

This kind of Intialization is really just some syntactic sugar around construction of a class and assigning values to properties, It is very useful for Anonymous classes and Linq select clauses.

Tim Jarvis
A: 

If you're asking if the new object initialization shorthand breaks encapsulation, then the answer is no. You can only set publicly scoped members with the new method.

MyClass test = new MyClass { _aString = "Test" };

is the same as

MyClass test = new MyClass();
test._aString = "Test";
Jamie Ide
A: 

To show an object public in a C# class does not break "encapsulation" from a point of view of "Object-oriented programming".

From a point of view of a "good practise" it not a good thing, use Properties because it allows to external code to use this class if you change the behaviour of updating this value (checking, ...).

FerranB