After seeing Microsoft to release Visual Studio 2010 RC version I have decided again to look at C#/.NET new and older versions just to look what C#/.NET can give us to solve problems. Today I am going to start looking at some C# language features what I find more interesting parts. In one or more posts I will try to go through all of the C# 4.0 features in coming weeks.
Anonymous Types
Anonymous Types were introduced in C# 3.0 and is supported on 3.5+ .NET. It allows us to create objects with read-only properties and we don't have to define new type for it. Let's look at example.
// Creating Anonymous Type
var rgbColor = new
{
red = 255,
blue = 255,
green = 255,
description = "White Color"
};
Console.WriteLine("Red: {0}, Blue: {1}, Green: {2} <-- {3}",
rgbColor.red, rgbColor.blue, rgbColor.green, rgbColor.description);
// Red: 255, Blue: 255, Green: 255 <-- White Color
Console.ReadKey(true);
In this example we created anonymous types with 4 properties. We used var statement which tells compiler to use type of the object from the right side. In this case this is anonymous type, but it also works with built-in or user defined types. We listed properties using objects and collections initializer, which I am going to look more deeply a bit later. Let's go to investigate how actually anonymous types do work.
Visual Studio does handle anonymous type properties too:

Point[] points = new Point[] { new Point(1, 1), new Point(2, 2), new Point(3, 3) };
var sqrPoints =
from point in points
select new { X = Math.Pow(point.X, 2), Y = Math.Pow(point.Y, 2) };
foreach (var point in sqrPoints)
{
Console.WriteLine("X: {0}, Y: {1}", point.X, point.Y);
}
// X: 1, Y: 1
// X: 4, Y: 4
// X: 9, Y: 9
Console.ReadKey(true);
In this example we create 3 points array and we using LINQ to create new collection of points but these points are going to have they X and Y in square. When you are using LINQ to go through records where each record might have dozen of parameters we can only take those we want. Let's say in this example we could have taken only X or Y in our anonymous type. It's much nicer to work with smaller objects and memory footprint should be lower too.
var rgbColor2 = new
{
red = 255,
blue = 255,
green = 255,
description = "White Color"
};
Console.WriteLine("Type: {0}", rgbColor2.GetType().ToString());
// Type: <>f__AnonymousType0`4[System.Int32,System.Int32,System.Int32,System.String]
Console.WriteLine("Type: {0}", rgbColor.GetType().ToString());
// Type: <>f__AnonymousType0`4[System.Int32,System.Int32,System.Int32,System.String]
Console.ReadKey(true);
Now we are getting to know how C# handles those types. If anonymous objects have identical count of properties, properties types and the order of those properties are the same then those anonymous objects have the same type. Remember this, because this is going to help us later.
object color = (object)rgbColor;
Console.WriteLine(color);
// { red = 255, blue = 255, green = 255, description = White Color }
var againColor = DynamicCast(color, new { red = 0, blue = 0, green = 0, description = "" });
Console.WriteLine("Red: {0}, Blue: {1}, Green: {2} <-- {3}",
againColor.red, againColor.blue, againColor.green, againColor.description);
// Red: 255, Blue: 255, Green: 255 <-- White Color
Console.ReadKey(true);
// Tomas Petricek, MVP
private static T DynamicCast(object value, T type)
{
return (T)value;
}
Here is interesting example. All anonymous objects are limited to method scope. This means that we can't pass it outside our method without some additional work. The only way to pass this anonymous object outside our method is to cast it to the object. This is the easy part, it's a bit more complicated to make it usable again. Tomas Petricek (MVP) has posted working solution for this. In the example before we find out that we can define identical anonymous types, this method is based on that idea. We create anonymous object and pass it's type to DynamicCast, DynamicCast function casts given object to this type and return it. The only problem is that Microsoft does not recommend passing anonymous object outside your function, it just brakes strong typing. I would suggest following this rule. This is just workaround that does work, but you should never be used.
Console.WriteLine("rgbColor HashCode: {0}", rgbColor.GetHashCode());
Console.WriteLine("rgbColor2 HashCode: {0}", rgbColor2.GetHashCode());
//rgbColor HashCode: 2113248095
//rgbColor2 HashCode: 2113248095
if (rgbColor.Equals(rgbColor2))
{
Console.WriteLine("They are equal.");
}
else
{
Console.WriteLine("They are not equal.");
}
// They are equal.
Console.ReadKey(true);
In this last example I wanted to show you that if types is the same for two anonymous objects with same count of properties, types and order of properties, Equals() and GetHashCode() works too. As you can see rgbColor and rgbColor2 anonymous objects has the same type and we can compare them using Equals() method.
MSDN Reading
http://msdn.microsoft.com/en-us/library/bb397696.aspx [Anonymous Types (C# Programming Guide)]
Object and Collection Initializers && Auto-Implemented Properties
Let's briefly look how those two features works in C# by looking at the examples. This is going to be mixed example.
class PlotPoint
{
private int _someInnerValue = 0;
// This is auto-implemented properties
public double X { get; set; }
public double Y { get; set; }
public string Title { get; set; }
// Additional auto-implemented properties
public double Length { get; }
public bool SetOnlyProperty { set; }
// standard property
public int Something
{
get
{
return -this._someInnerValue;
}
set
{
this._someInnerValue = value * 2;
}
}
}
This is out special class for the next example. This class demonstrates how to you can use properties. First three properties are auto-implemented with ability to set and get them without writing the body for setter and getter while the next two shows that you can define just one of them. In short words, "set;" or "get;" will be auto-implemented properties. This is the shortest way to define getter and setter.
var point = new PlotPoint() { X = 10, Y = 10 };
var point2 = new PlotPoint() { X = 0, Y = 0, Title = "Hello Point", Something = 10, SetOnlyProperty = true };
var point3 = new PlotPoint() { Title = "Start Coord" };
List list = new List() { 0, 1, 2, 3, 4, GiveMeFive(), 6, 7, 7 + 1, 7 + 2 };
List list2 = new List()
{
new PlotPoint() { X = 0, Y = 0, Title = "Start Point" },
null, // Point to compute
null, // Point to compute
new PlotPoint() { X = 1, Y = 1, Title = "Some Middle Point" },
null, // Point to compute
null, // Point to compute
new PlotPoint() { X = 2, Y = 2, Title = "End Point" }
};
public static int GiveMeFive()
{
return 5;
}
This one demonstrates how to use object and collection initializers. In the first three lines we initialize PlotPoint objects and using initializer we define some properties. You can set as many properties you need to. Each property can only be set once in the initializer list. The last two objects are lists. Here we combine both object and collection initializers. It is allowed to use null, other methods, operations and etc. in those lists.
MSDN Reading
http://msdn.microsoft.com/en-us/library/bb384062.aspx [Object and Collection Initializers (C# Programming Guide)]
http://msdn.microsoft.com/en-us/library/bb384054.aspx [Auto-Implemented Properties (C# Programming Guide)]