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