Saturday, November 13, 2010

How to: Implement a Lightweight Class with Auto-Implemented Properties


in my previous article i have discussed about Auto implemented properties. In this example I will shows how we can create an immutable lightweight class which will serve the purpose only to encapsulate a set of auto-implemented properties. We can use this kind of construct in place of a struct when we must use reference type semantics.
Note that in case of auto-implemented properties, both a get and set accessor are required. We make the class immutable by declaring the set accessors as private(Yes this is possible in C#). However, declaring a private set accessor, we cannot use an object initializer to initialize the property. For this we must use a constructor or a factory method.
Example
The following example shows two ways to implement an immutable class that has auto-implemented properties. The first class uses a constructor to initialize the properties, and the second class uses a static factory method.
//ClassA
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LightweightClass
{
    // This is an immutable class. Once an object is created, it cannot be modified outside the class. It only uses its constructor to initialize properties.
    class ClassA
    {
        // Read-only properties.
        public string Property1 { get; private set; }
        public string Property2 { get; private set; }

        // Public constructor.
        public ClassA(string Value1, string Value2)
        {
            Property1 = Value1;
            Property2 = Value2;
        }
    }
}


//ClassB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LightweightClass
{
    // This is an immutable class. Once an object is created, it cannot be modified outside the class. It only uses its constructor or the public Factory Mthod to initialize properties.
    public class ClassB
    {
        // Read-only properties.
        public string Property1 { get; private set; }
        public string Property2 { get; private set; }

        // Private constructor.
        private ClassB(string Prop1, string Prop2)
        {
            Property1 = Prop1;
            Property2 = Prop2;
        }

        // Public factory method.
        public static ClassB CreateObject(string prop1, string prop2)
        {
            return new ClassB(prop1, prop2);
        }
    }


}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace LightweightClass
{
    public class Program
    {
        static void Main()
        {
            // Some simple data sources.
            string[] names = {"Meetu Choudhary","Gaurav Arora", "Prabhjeet Gill",
                              "Nikita Rathi", "Manpreet Kaur"};
            string[] addresses = {"29 Jaipur", "12 Gaziabad.", "678 1st Ave",
                                  "12 Tonk", "89 Et. Mumabi"};

            // Simple query to demonstrate object creation in select clause.
            // Create objects of ClassA by using a constructor.
            var query1 = from i in Enumerable.Range(0, 5)
                         select new ClassA(names[i], addresses[i]);

            // List elements cannot be modified by client code.
            var list = query1.ToList();
            Console.WriteLine("Using Constroctor");
            foreach (var contact in list)
            {
                Console.WriteLine("{0}, {1}", contact.Property1 , contact.Property2 );
            }

            // Create ClassB objects by using a static factory method.
            var query2 = from i in Enumerable.Range(0, 5)
                         select ClassB.CreateObject(names[i], addresses[i]);

            // Console output is identical to query1.
            var list2 = query2.ToList();
            Console.WriteLine("Using Factory Method");
            foreach (var contact in list2)
            {
                Console.WriteLine("{0}, {1}", contact.Property1, contact.Property2);
            }
            // List elements cannot be modified by client code. this will gentrate the error
            // CS0272:
            // list2[0].Name = "Eugene Zabokritski";

            // Keep the console open in debug mode. to check
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Output

Using Constroctor
Meetu Choudhary, 29 Jaipur
Gaurav Arora, 12 Gaziabad.
Prabhjeet Gill, 678 1st Ave
Nikita Rathi, 12 Tonk
Manpreet Kaur, 89 Et. Mumabi
Using Factory Method
Meetu Choudhary, 29 Jaipur
Gaurav Arora, 12 Gaziabad.
Prabhjeet Gill, 678 1st Ave
Nikita Rathi, 12 Tonk
Manpreet Kaur, 89 Et. Mumabi
Press any key to exit.

Auto Implemented Properties


Auto Implemented Properties
In C# 3.0 and later, We have an easy, interesting way for declaring properties known as auto-implemented properties, These Auto implemented properties are especially used when there is no additional logic required in the property accessors. When a property is declared as using Auto Implementation as shown in the example below, compiler creates a private, anonymous backing field or you can say it a member which can be only accessed through the property's get and set accessors.

Example


The following example shows a simple class that has some auto-implemented properties:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutoImplemented_Properties
{
    // This class is mutable. Its data can be modified from
    // outside the class.
    class Student
    {
        // Auto-Impl Properties for trivial get and set
        public double TotalMarks { get; set; }
        public string StudentName { get; set; }
        public int RollNo { get; set; }

        // Constructor
        public Student(double marks, string name, int Rno)
        {
            TotalMarks = marks;
            StudentName = name;
            RollNo = Rno;
        }
        // Methods
        public string GetStudentInfo()
        {
            return "Student Information : " + StudentName + " " + RollNo.ToString() + " " + TotalMarks.ToString();
        }
        public string GetMarks()
        {
            return "Marks : " + TotalMarks.ToString();
        }

        // .. Additional methods, events, etc.
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AutoImplemented_Properties
{
    class Program
    {
        static void Main(string[] args)
        {
            // Intialize a new object.
            Student Stud1 = new Student(987.50, "Meetu Choudhary", 90108);
            Console.WriteLine("Marks Before Modification");
            Console.WriteLine(Stud1.GetMarks());
            //Modify a property
            Stud1.TotalMarks += 499.99;
            Console.WriteLine("Marks After Modification");
            Console.WriteLine(Stud1.GetMarks());
            Console.WriteLine("Complete information of Student");
            Console.WriteLine(Stud1.GetStudentInfo());
            Console.ReadLine();
        }
    }
}

Output
Marks Before Modification
Marks : 987.5
Marks After Modification
Marks : 1487.49
Complete information of Student
Student Information : Meetu Choudhary 90108 1487.49


Code Discussion
  • Auto implemented properties are declared using the following line:
public double TotalMarks { get; set; }

·         Value of the property is increased by the object as  it is an Mutable class.

Stud1.TotalMarks += 499.99;

Note:
The class that is shown in the above example is mutable i.e. Client code has the power to change the values of objects after they are created. However, in complex classes that contain significant behavior (methods) and data, it might be a necessary to have public properties. but, for small classes or structs that may just encapsulate a set of values (data) with little or no behaviors (or Methods), it is recommended to make the objects which are immutable by declaring the set accessor as private. Attributes are permitted on auto-implemented properties but not on the backing fields as these fields are not accessible from our source code. If it is necessary to use an attribute on the backing field of a property, then just create a regular property instead of auto implemented property. For more information, see
How to: Implement a Lightweight Class with Auto-Implemented Properties 
To know about properties in C# read this article
For reading on Abstract Properties click here

Subscribe via email

Enter your email address:

Delivered by FeedBurner

MSDotnetMentor

MSDotnetMentor My Website http://msdotnetmentor.com