Anonymous types that have been introduced in C# with .NET 3.5 is a convenient and powerful feature and can be used to simplify and speed up development without sacrificing code quality or violating coding standards.
Perhaps one most widely known application is to use anonymous types in a context of LINQ expressions since that is mentioned on MSDN in most of the anonymous types related examples. Such strong association between anonymous types and LINQ though being true creates a wrong impression of that LINQ is the only application for anonymous types an perhaps discourages many developers from discovering many other ways of utilizing anonymous types. For example, I could mention returning anonymous type object from a JSON enabled ASP.NET Web, WCF or MVC service method which is extremely beneficial due to anonymous types being very lightweight and readily JSON serializable. However that is a topic for another article.
When considering their applicability anonymous types frequently declined to be used due to their local scope visibility that is usually considered an unbreakable obstacle. What that means is an anonymous type object can only be used inside a code scope where it was defined with the largest scope being a method scope. In other words an anonymous type object cannot be used as a strongly typed object outside of its scope of visibility since its type does not exist in an outer scope from the compiler point of view. For example, if an anonymous object returned from a method it can only be seen and used as a base C# object type which makes it totally useless from a conventional point of view since its properties and their values are not accessible. Compiler will throw an error on any attempt to cast an anonymous type object to any other type. Based on the above the obvious conclusion would be to not continue down this road and consider the topic closed. That is however not true.
With another powerful feature introduced in C# by .NET 4 called dynamic types anonymous types are given even more reasons to be used since they now can be used outside of their scope of visibility. Sounds fantastic? Let me show you how it's done.
Let's consider a usual scenario when there is a long list of complex objects that is used as a data source and we need to select several objects from that list and display some of their properties. Old school approach would be to define a POCO type that consists of properties to display, iterate through the original list and build a new list of POCO objects populated from the data source properties and then bind that list of POCO objects to a visual control that displays the output. Nothing is wrong with that except that a new POCO type must be defined even if it's not going to be reused anywhere else. That requires additional coding and future maintenance if the content that should be displayed changes. With anonymous types we can avoid creating a POCO type by using an anonymous type instead and providing a list of anonymous objects as a data source for the visual control. That will work just fine as long as no additional data processing is required against the list of the anonymous objects. Often however it is required to perform some additional processing against a newly build data source which is now a list or anonymous objects and this is where the problem occurs: it is not possible to access properties of an anonymous object outside of a method where this object was created. Is it true though?
A dynamic keyword allows to overcome this problem as it instructs compiler to not perform a compile time type check and leave that to the run-time environment. As such we can write a C# code that operates with an anonymous object as it was a strongly typed object. See the code example below:
object[] GetList()
{
// Elements is a long list of complex objects
var result = new ArrayList();
foreach (var element in Elements)
{
if (/*condition to select a single element */)
{
result.Add(new { P1 = elemet.Prop1, P2 = element.Prop2, P3 = element.Prop3 });
}
}
return result.ToArray();
}
// Note: input parameter el is declared as dynamic
void ProcessElement(dynamic el)
{
// Cool! For a dynamic type compiler allows accessing properties by names
var p1 = el.P1;
var p2 = el.P2;
var p3 = el.P3;
// Now we can do something that we need with an anonymous object!
}
void PerformLogic()
{
var list = GetList();
foreach (var element in list)
{
ProcessElement(element);
}
// do something else...
}
I assume comments are not required for the example as it speaks for itself. Just try and use this cool technique in your next project and see how much time and headache you'll save.
Just to reiterate: anonymous types is a powerful feature that helps create cleaner and better code however it has some limitations. Using a dynamic keyword allows to overcome limitations of the anonymous types.
No comments:
Post a Comment