Thursday, May 12, 2011

Object Initializers and Collection Initializers

New C# Language Features: Automatic Properties, Object Initializers, and Collection Initializers

Question arises:

  1. if we use properties like obj.property then why not make those field public even then we can access them like obj.field.

  2. Second, if you've got a non-private field, why should you make it private and expose a property instead?

    Solution 1. first thing is that if You can use a property everywhere you can use a field, right? Wrong. You can use a field for ref parameters, whereas you can't (in C# at least) use a property in the same way. There are other subtle areas where there's a difference between fields and properties.

    Second thing is


What are properties?
Just normal variables, like other primitive variables!

Example A:
/////////// ExA.cs //////////////
namespace Rahul
{
using System ;

class Colors
{
public static void Main()
{
UrChoice UrColor = new UrChoice() ;

//Overwriting your favourite color to yellow
UrColor.Color = \"Yellow\" ;
Console.WriteLine(\"Your favourite color is \" + UrColor.Color) ;
}
}

public class UrChoice
{
// Want to provide the access to everybody.
public string Color ;

// Default Constructor setting up your favourite color
public UrChoice()
{
Color = \"White\" ;
}

}

}

Compile the program as: csc ExA.csNow type ExA and press enter (return) key…Output is: Your favorite color is Yellow

In Example 'A', I have declared two classes inRahul namspace:One is UrChoice (as the names are self explanatory) is talking aboutyour choice, not all of your choices but here we are discussing aboutyour favorite color and you have fixed your favorite color as "White"(Just for an instance). Now everybody is free to know about yourfavorite color and he can tell others about your choice.

But there is a problem!
Somebody has changed the value of your favorite color and now your favorite color is Yellow.
Hey! That?s cheating!!!!
Yes! Of course but is there any way to protect your variable or your choice?
Here comes the turn of properties.

Properties are like normal variables but with more power and flexibility.Now we convert the color variable in a property with the same name.

Example B:
////////// ExB.cs //////////////
namespace Rahul
{

using System ;

class Colors
{
public static void Main()
{
UrChoice UrColor = new UrChoice() ;

//Overwriting your favourite color to yellow
UrColor.Color = \"Yellow\" ;
Console.WriteLine(\"Your favourite color is \" + UrColor.Color) ;
}
}

public class UrChoice
{
// your private variable to store your favourite color
private string MyColor ;

// Defining property, Want to provide the access to everybody.
public string Color
{
get{
return MyColor ;
}
}

// Default Constructor setting up your favourite color
public UrChoice()
{
MyColor = \"White\" ;
}
}

}

This time we didn't define color variable as anormal variable rather we defined a property named Color.But in this case we had to define a new variable MyColor to store theinitial and right value of your favorite color (also making it privateto hide it from outside world).
This time when we try to compile our program as: csc ExB.cs
We get an error:
Property or indexer ' Rahul.UrChoice.Color ' can not be assigned to — it is read only.

So, we got actually what we wanted. Now if somebody tries to modify your favorite color, he can not do this.

If you are a C# developer today, you are probably quite used to writing classes with basic properties like the code-snippet below:

public class Person {

private string _firstName;
private string
_lastName;
private int
_age;

public string
FirstName {

get {
return _firstName;
}
set {
_firstName
= value;
}
}

public string LastName {

get {
return _lastName;
}
set {
_lastName
= value;
}
}

public int Age {

get {
return _age;
}
set {
_age
= value;
}
}
}

The new C# compiler that ships in "Orcas" provides an elegant way to make your code more concise while still retaining the flexibility of properties using a new language feature called "automatic properties". Automatic properties allow you to avoid having to manually declare a private field and write the get/set logic -- instead the compiler can automate creating the private field and the default get/set operations for you.

For example, using automatic properties I can now re-write the code above to just be:

public class Person {

public string FirstName {
get; set;
}

public string LastName {
get; set;
}

public int Age {
get; set;
}
}

Or If I want to be really terse, I can collapse the whitespace even further like so:

public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}



C# 3.0 Automatic Properties explained



So here's the code sample I'm talking about:

 1 using System;  2   3 namespace ConsoleApplication1  4 {  5     class Program  6     {  7         public string Name { get; set; }  8   9         static void Main(string[] args) 10         { 11             var p = new Program(); 12             p.Name = "Bart"; 13         } 14     } 15 }

The clue is on line 7 where I've declared an automatic property. Basically this frees me from the burden of declaring a private variable and a get and set accessor to it by means of a property. Although you can just use the "prop" code snippet in Visual Studio, this is much cleaner in case you don't need the private fields at all. Imagine some entity mapping class that consists of 20 properties, do you want to see all of the private variable, getter and setter noise around your class? I don't think so.

Please notice that the use of automatic properties is not equal to just defining a public field - you still keep the get_PropertyName and set_PropertyName methods behind the scenes as well as all the metadata that goes with a property, as illustrated below:

This means your code can be upgraded at any time to define getters/setters together with an explicitly defined member variable when you need to do so, without having to recompile external consumers of your code (i.e. the "contract" remains untouched). Behind the scenes what happens is the injection of a private member variable, prefixed with <>k__AutomaticallyGeneratedPropertyField#, like this:

.field private string '<>k__AutomaticallyGeneratedPropertyField0' .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) 

The CompilerGeneratedAttribute attribute is useful for tools to find out about these auto-generated things. Next, the compiler emits a getter and setter for you:

.method public hidebysig specialname instance string          get_Name() cil managed {   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )    // Code size       11 (0xb)   .maxstack  1   .locals init (string V_0)   IL_0000:  ldarg.0   IL_0001:  ldfld      string ConsoleApplication1.Program::'<>k__AutomaticallyGeneratedPropertyField0'   IL_0006:  stloc.0   IL_0007:  br.s       IL_0009   IL_0009:  ldloc.0   IL_000a:  ret } // end of method Program::get_Name  .method public hidebysig specialname instance void          set_Name(string 'value') cil managed {   .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 )    // Code size       8 (0x8)   .maxstack  8   IL_0000:  ldarg.0   IL_0001:  ldarg.1   IL_0002:  stfld      string ConsoleApplication1.Program::'<>k__AutomaticallyGeneratedPropertyField0'   IL_0007:  ret } // end of method Program::set_Name

All the stuff in here is pretty much the same as a manually defined property, except for the presence of the CompilerGeneratedAttribute attribute. Finally, there's the metadata for the property:

.property instance string Name() {   .get instance string ConsoleApplication1.Program::get_Name()   .set instance void ConsoleApplication1.Program::set_Name(string) } // end of property Program::Name

Notice that "automatic properties should have both a getter and a setter" declared. Read-only or write-only properties are not permitted. After all, a typical use for automatic properties is to define "property bag" kind of classes or structs. Of course, there's IntelliSense too:

With the screenshot above I've also shown that local type inference (keyword "var") has now full IDE support (i.e. when you type p. the IDE already knows the type of the variable in order to provide accurate IntelliSense). Enjoy!


Object Initializers

To get started, let's look at the standard way of initializing an object with data in C# 2.0 using constructors. The following example creates a Person object and passes three values to its constructor.

Person person = new Person("Scott", "Guthrie", "32");

As mentioned, C# 3.0 now supports the concept of "object initializers" which means you can easily assign data to specific properties in a type without having to create an explicit constructor (you can of course still create constructors as well). The standard C# { and } brackets are used to create object initializers. Here's an example of using an object initializer to assign property data to a Person type. It's nice because doing the same thing without using a constructor in C# 2.0 would have resulted in around 5 lines of code which is too many for something simple like property value assignments.



Types within the .NET Framework rely heavily on the use of properties. When instantiating and using new classes, it is very common to write code like below:

Person person = new Person();
person.FirstName = "Scott";
person.LastName = "Guthrie";
person.Age = 32;

Have you ever wanted to make this more concise (and maybe fit on one line)? With the C# and VB "Orcas" compilers you can now take advantage of a great "syntactic sugar" language feature called "object Initializers" that allows you to-do this and re-write the above code like so:

Person person = new Person { FirstName="Scott", LastName="Guthrie", Age=32 };

The compiler will then automatically generate the appropriate property setter code that preserves the same semantic meaning as the previous (more verbose) code sample above.

Collection Initializers

New C# and VB Language Feature: Collection Initializers

Object Initializers are great, and make it much easier to concisely add objects to collections. For example, if I wanted to add three people to a generics-based List collection of type "Person", I could write the below code:

List people = new List();

people.Add( new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 } );
people.Add( new Person { FirstName = "Bill", LastName = "Gates", Age = 50 } );
people.Add( new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 } );



List people = new List();

people.Add( new Person { "Scott", "Guthrie", 32 } );
people.Add( new Person { "Bill", "Gates", 50 } );
people.Add( new Person {"Susanne", "Guthrie",32 } );

//above one using constructor

Using the new Object Initializer feature alone saved 12 extra lines of code with this sample versus what I'd need to type with the C# 2.0 compiler.

The C# and VB "Orcas" compilers allow us to go even further, though, and also now support "collection initializers" that allow us to avoid having multiple Add statements, and save even further keystrokes:

List people = new List {
new Person { FirstName = "Scott", LastName = "Guthrie", Age = 32 },
new Person { FirstName = "Bill", LastName = "Gates", Age = 50 },
new Person { FirstName = "Susanne", LastName = "Guthrie", Age = 32 }
}
;

When the compiler encounters the above syntax, it will automatically generate the collection insert code like the previous sample for us.



No comments:

Post a Comment