locked
Encapsulation, when to use and when not... RRS feed

  • Question

  • In general when I build a class that has fields I want to able to access I always encapsulate them.  My philosophy up to this point has been to encapsulate every field unless I can think of an explicit case where this would become a problem.  Haven't given it much thought up until now, and I am wondering if I may be missing some key point and am unnecessarily creating a bunch of get/set code when I don't really need to.  I would be interested in others folks's take on this. Thanks

    Friday, August 28, 2009 5:36 PM

Answers

All replies

  • There's no reason not to in C#.  Use the automatic properties if you don't have any bulky code to deal with:

    public int Value { get; set; }

    Can't be that much harder than:

    public int Value;

    And it offers encapsulation.

    Keep in mind that the JIT compiler will optimize your "simple" properties, and have the runtime just modify the field.

    Use encapsulation. 
    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiTwitterLinkedInForumsBrowser
    • Marked as answer by mathiasX Friday, August 28, 2009 6:22 PM
    Friday, August 28, 2009 5:39 PM
  • When you serialize a class, you cannot serialize fields....only properties.

    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, August 28, 2009 5:57 PM
  • When you serialize a class, you cannot serialize fields....only properties.

    Mark the best replies as answers. "Fooling computers since 1971."


    Let me beg to differ.

    This is only the case for XmlSerializer and for DataContracts that have a DataMember attribute over the property.  BinaryFormatter serializes only the fields, and views the properties as nothing but methods, leaving them alone entirely.  When it deserializes, it never calls the code within the properties, it simply sets the fields. 

    WCF DataContractSerializer will allow you to serialize either, but will only serialize items marked with [DataMember].

    Here's an example to prove the point, for the skeptical. 

    using System;
    using System.IO;
    using System.Runtime.Serialization.Formatters.Binary;

     

    namespace ConsoleApplication31
    {
        internal class Program
        {
            private static void Main(string[] args)
            {
                var thing = new StrangeThing();
                thing.SetValue(5);
                Console.WriteLine(thing.Value);

     

                var formatter = new BinaryFormatter();
                var stream = new MemoryStream();
                formatter.Serialize(stream, thing);

     

                stream.Position = 0;

     

                var thing2 = (StrangeThing) formatter.Deserialize(stream);

     

                Console.WriteLine(thing2.Value);
                Console.WriteLine("Setter was never called");
            }
        }

     

        [Serializable]
        internal class StrangeThing
        {
            private int _value;

     

            public int Value
            {
                get { return _value; }
                set { throw new NotImplementedException(); }
            }

     

            public void SetValue(int value)
            {
                _value = value;
            }
        }
    }


    Coding Light - Illuminated Ideas and Algorithms in Software
    Coding Light WikiTwitterLinkedInForumsBrowser

    Friday, August 28, 2009 5:59 PM
  • True, but the XML Serializer is becoming more and more popular to use because it is not platform specific.
    The Binary Serializer is only good with other .NET software, whereas most anything can read XML files.

    Mark the best replies as answers. "Fooling computers since 1971."
    Friday, August 28, 2009 6:18 PM
  • I forgot about the  { get; set; } shorthand version.  That trims up my code quite a bit. thanks!
    Friday, August 28, 2009 6:22 PM
  • In C#, all public fields (data members) are effectively encapsulated.  The reason is that even after much client code has been written in other classes that access the public data member, the original class can be revised to include a property for that member, and the original public data member renamed and marked private.  The new private field is then accessed only through the newly created property which is given the name of the original public field.  If this is done, then no client code need be modified.  The big deal about encapsulation was that in earlier OO languages, changing a public field to private, and adding a getter and setter, always forced the client code to be rewritten.

    For example, you can write a class: 

    public class Thermostat
    {
     /// <summary>
     /// In centigrade degrees.
     /// </summary>
     public double temperature
    }
    
    
    Then later, due to instrument hardware changes, change the class to: 
    public class Thermostat
    {
     private double kelvinDegrees;
    
     /// <summary>
     /// In centigrade degrees.
     /// </summary>
     public double temperature
     {
     get
     {
        return kelvinDegrees - 273.15;
     }
    
     set
     {
        kelvinDegrees = value + 273.15;
     }
    
     }
    
    }
    
    
    The code that accesses "temperature" is the same whether it accesses it through the original public data member, or later, through the property.  That is the important thing about whether encapsulation is maintained.  Very few public data members will ever need to be converted to properties, so why bother with the extra syntax when initially writing them?  Why not just start them all off as public fields, then in the rare case where a function is later desired to be interposed during the access one of them, change it later as needed.
    OOP/OOD became important when programs got huge; in such cases, there are many more lines of code that call a method or access data in a class, than there are lines in that class that provide the access.  That is why the crucial point about encapsulation, is its effect on client code-- that is whether changes to a class' implementation require modification to clients of that class.
    I think the effective encapsulation of public fields was one of the most brilliant original design features of C#.  As I recall, the original syntax required in C# 1.0, was much more cumbersome than the vestigial "{get; set}", so it was a bigger deal at the time.  Now there is little difficulty in just appending the vestigial "{get; set}" after every data member that would otherwise be a plain field.  But to me, it seems better OOP to explicitly exploit the effective encapsulation of public fields in C#, rather than covering it up with vestigial getters and setters for all data.
     
    • Proposed as answer by c4dn Wednesday, April 6, 2011 8:51 AM
    Wednesday, April 6, 2011 8:38 AM
  • After doing further research, I found some advantages to retaining the { get; set; } appendix to what would otherwise be public fields.  If you start off without it, and other people build or receive client DLLs that call your code, when you later change the field to a property, the clients will have to be recompiled.  That's much easier than modifying client code, but some people would not like having to do that unnecessarily.  Furthermore, there may be some unforeseen consequences to using a field rather than a property, for serialization or persistence. 
    Sunday, April 17, 2011 9:23 AM
  • Of course we all know that getters and setters are "evil" - http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html?page=1 (LOL).

    Regards David R
    ---------------------------------------------------------------
    Every program eventually becomes rococo, and then rubble. - Alan Perlis
    The only valid measurement of code quality: WTFs/minute.
    Sunday, April 17, 2011 10:28 AM