Beautiful Code

by James Shaw 13. March 2009 22:07
When coding recently, I found myself greatly appreciating C#'s rich features that reduce the number of lines of code written.  Let me elaborate.

There has been so many times when I find myself wanting to access a list of objects randomly, based on some field of that object.  To do it efficiently I'd want to use a dictionary to to access these objects, with the key being the field I want to find the object by.  This need happens so often with lists of different types of object (say from 3rd party API's you use) that it's best to write a generic helper function that can wrap a list of any type of object with a dictionary and returns that dictionary, rather than writing a helper function for list of each type of object.  The following is such code, using generics and reflection in C#:
 
    public class Util
    {
        ...
        /// <summary>
        /// generic method that wraps the given IEnumerable into a IDictionary with the given
        /// field (of the objects in IEnumerable) as the key.
        /// </summary>
        /// <typeparam name="KeyType"></typeparam>
        /// <typeparam name="ValType"></typeparam>
        /// <param name="src"></param>
        /// <param name="keyFieldName"></param>
        /// <returns></returns>
        public static IDictionary<KeyType, ValType> ToDictionary<KeyType, ValType>(IEnumerable<ValType> src,
                                                                                   string keyFieldName) 
            where KeyType : class
            where ValType : class
        {
            var ret = new Dictionary<KeyType, ValType>(src.Count() );

            foreach (ValType ele in src)
            {
                var key = typeof(ValType).GetProperty(keyFieldName, typeof(KeyType) ).GetValue(ele, null) as KeyType;
                ret[key] = ele;    
            }

            return ret;
        }

    }
 
With the above you can access a list of any objects like this:
 
            var attendeesById = Util.ToDictionary<string, Attendee>(attendees, "Id");
 
Here for example it assumes Attendee class contains an "Id" string property.  You can use Util.ToDictionary with IEnumerable of any other types of objects. 

Another good use of generics to reduce code I had was when parsing XML; when parsing XML frequently you want to parse an element's value to a .Net type, using int.parse() for example, if the element is supposed to contain an int.  Well I would just use int.parse() to do the job except that sometimes the element can be optional, so it's again nice to have a generic helper method that takes in an XML element and returns the appropriate type after parsing, or null if it's optional.  For example, when using the following code to parse XML,
 
    WebRequest httpRequest = HttpWebRequest.Create(url);
    using (var httpResponseStream = httpRequest.GetResponse().GetResponseStream())
    {
        var xmlRoot = XElement.Load(XmlReader.Create(httpResponseStream));
        var xmlNamespace = XNamespace.None;
        ret = new List<Event>(from result in xmlRoot.Descendants(xmlNamespace + "item")
                                    select new Event()
                                    {
                                        Id = XmlUtil.GetXElementValue(result.Element("id"), true),
                                        Name = XmlUtil.GetXElementValue(result.Element(xmlNamespace + "name"), true),
                                        Description = XmlUtil.GetXElementValue(result.Element(xmlNamespace + "description"), false),
                                        VenueName = XmlUtil.GetXElementValue(result.Element(xmlNamespace + "venue_name"), false),
                                        VenueLatitude = Util.ParseOptional<double>(XmlUtil.GetXElementValue(result.Element(xmlNamespace + "venue_lat"), false)),
                                        VenueLongitude = Util.ParseOptional<double>(XmlUtil.GetXElementValue(result.Element(xmlNamespace + "venue_lon"), false)),

                                        ... 
                                    });
 
The following helper methods in Util come in handly, esp Util.ParseOptional, which is shared code to parse any type that I want to parse out of XML and that has a parse method.  The more shared code (i.e., the less code a developer writes) the less chance for bugs :).
 
    public class XmlUtil
    {
        ...
        public static string GetXElementValue(XElement xe, bool required)
        {
            string ret = null;

            if (xe != null)
            {

                if (xe.Value != null)
                {
                    ret = xe.Value.Trim();
                }
                else if (required)
                {
                    throw new Exception(xe.Name + " should contain a value");
                }
            }
            else if (required)
            {
                throw new Exception("required XML element is missing");
            }

            return ret;
        }

    } // XmlUtil class


    public class Util
    {
        /// <summary>
        /// generic method that parses the given string to the given type, taking into account
        /// that the given string might be null.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="arg"></param>
        /// <returns></returns>
        public static Nullable<T> ParseOptional<T>(string arg) where T : struct
        {
            Nullable<T> ret = null;

            if (!string.IsNullOrEmpty(arg) )
            {
                var methodInfo = typeof(T).GetMethod("Parse",
                                                     new Type[] { typeof(string) });
                ret = methodInfo.Invoke(null, new object[] { arg }) as Nullable<T>;

            }

            return ret;
        }
 
 In summary, I find .Net's generics and reflection features very helpful in abstracting functionality further and reducing even more lines of code written.  The other features demonstrated in the snippets like Linq to Xml, variable type inference (the "var" keyword), and object initializer (the ability to initialize properties in constructor) also help a lot in writing less code, and really speed up development.  I recently had to switch coding between C# and Java, and what a difference it was without them: the Java code is a lot more lines (and thus more chance for bugs) and you just end up typing more.  
 
Java was a revolutionary language (and I learned it before C#) but it seems like in the evolution of languages C# has surpassed it (at least in terms of the core language features).  

Powered by BlogEngine.NET 1.4.5.0
Theme by Extensive SEO