Skip to content

Archive

Tag: C#

If you have been programming in C# for a little while then you probably already have seen a couple of extension methods by now. What I did notice however was that there are clearly 2 different kind of developers making those extension methods. It looks like that there are developers who strive to make the best looking and most useful and well written extension methods and the other group of developers is trying to make an extension method out of everything. In order to be able to say what is good practice and what is bad, we are going to look at a couple of extension methods.

The first extension method that we are going to look at is compact and easy to use. At the other hand It’s also not so difficult to just write out what it does in your code. Here is the extension method:

public static bool IsBetween<T>(this T value, T low, T high) where T : IComparable<T>
{
    return value.CompareTo(low) >= 0 &amp;&amp; value.CompareTo(high) <= 0;
}

In our code we are now able to use this extension method like this:

if(user.Age.IsBetween(12, 16)) { ..

instead of what we would usulay do:

if(user.Age > = 12 &amp;&amp; user.Age <= 16) { ..

In this case I do think that the extension method does make the code a little better to read. Another plus is that the extension will only show up for something that implements the IComparable interface so that we will not get intellisence ‘pollution’.

Here is another extension method with a little more code:

public static string RemoveNonNumeric(this string s)
{
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < s.Length; i++)
    if (Char.IsNumber(s[i]))
        sb.Append(s[i]);
    return sb.ToString();
}

And you can use this extension method like this:

"(020) 555-555-123".RemoveNonNumeric();

I think this one falls in the category ‘sure, use it’. For me it’s as clear as using a trim function.

Ok, here are the last two extension methods for where I think there is little discussion over. These 2 extension methods will help you converting strings or numbers back to an enum. Here is the code:

        public static T ToEnum<T>(this int number)
        {
            return (T)Enum.ToObject(typeof(T), number);
        }
        public static T ToEnum<T>(this string text)
        {
            return (T)Enum.Parse(default(T).GetType(), text);
        }

And these extension methods can be used like this:

MyStatusEnum status = 1.ToEnum<MyStatusEnum>();
status = "Good".ToEnum<MyStatusEnum>();

You do will see the ToEnum extension method in the intelisence of every string and integer, but you do have to specify the enum type that you want to cast it to.

Here it comes. We are now going into the grey area. Below you can see a series of extension methods that will let you use every String.Format combination as a FormatWith extension method. These extension methods are used in more than one project that I have worked on and there have been various discussions about if these were good or bad. I think both sides are partially right. Here is the code:

public static string FormatWith(this string format, object arg0)
{
    return string.Format(CultureInfo.InvariantCulture, format, arg0);
}
public static string FormatWith(this string format, object arg0, object arg1)
{
    return string.Format(CultureInfo.InvariantCulture, format, arg0, arg1);
}
public static string FormatWith(this string format, object arg0, object arg1, object arg2)
{
    return string.Format(CultureInfo.InvariantCulture, format, arg0, arg1, arg2);
}
public static string FormatWith(this string format, params object[] args)
{
    return string.Format(CultureInfo.InvariantCulture, format, args);
}
public static string FormatWith(this string format, IFormatProvider provider, params object[] args)
{
    return string.Format(provider, format, args);
}

With these extension methods you are now able to write code like:

"Hello {0}, my name is {1}".FormatWith("you","Edwin");

Instead of the usual:

String.Format("Hello {0}, my name is {1}", "you","Edwin");

When I first looked at these extension methods I too thought I could as well just use the existing String.Format method. And then it also has the disadvantage that you will lose the compile time check for the number of parameters in your call. But then I noticed that during coding the.FormatWith often feels more natural to use. By now I am using the .FormatWith more and more.

The previous extension methods are a little dubious but I think the next couple of methods are more wrong than right. At first these extension methods look handy but then when you start using them you will see that they could be confusing. Here is the code:

public static int MilisecondsToSeconds(this int num)
{
   return num / 1000;
}
public static int SecondsToMiliseconds(this int num)
{
   return num * 1000;
}
public static int MinutesToMiliseconds(this int num)
{
   return num * 60000;
}

You can then start using these extension methods like this:

Thread.Sleep(5.SecondsToMiliseconds());
proxy.Timeout = 1.MinutesToMiliseconds();

At first this code looks ok to use, however it is also possible to use code like this:

int minutes = 5;
Thread Sleep(minutes.SecondsToMiliseconds());

With this code the mistake is obvious , but when you start using variables without ‘minutes’ in its name, this mistake is easier to make. One other thing is that intelisence will show you the SecondsToMiliseconds method for every integer there is. I think that if for most values an extension method does not apply, then you should not have that extension method. Instead you could use a class with a static method like this:

Thread.Sleep (Convert. SecondsToMiliseconds (5));

Here is another simple extension method that falls in the same category:

        public static Uri ToUri(this String uri)
        {
            return new Uri(uri);
        }

You can use this extension method like this:

            Uri myUri = "http://www.evict.nl".ToUri();

With this extension method intelisence will let you see the ToUri on every string.

Here is another nice example of an extension method that looks very cool and easy to use but should actually be avoided. Here is the code:

public static Boolean And(this Boolean b,  Boolean  expression)
{
    return b &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; expression;
}
public static Boolean Or(this Boolean b, Boolean expression)
{
    return b || expression;
}

You can then use these extension methods like this:

string myVal = ...
if(String.IsNullOrEmpty(myVal).Or(myVal=="N/A")) { ..

This extension method does not make your code more readable. Instead you could as wel use this code:

if(String.IsNullOrEmpty(myVal)  || myVal=="N/A") { ..

I don’t see any benefit for using this extension method. Instead you will just add some extra complexity to your project.

I do like to use extension methods. Especially when I can use it using generic types like the enum conversion methods at the beginning of this article.

After generating classes and properties using the Entity Framework or Linq2sql you somtimes want to know in your code how big a database field is. Probably that would be for doing some input validation. The best way to do that is of course asking that information from the database.

But wait… Didn’t we made a .dbml which generated a couple of classes for the tables in our database? The information we need should be in one of the files that is generated by the .dbml. When you search through the .cs file for your classes and fields, you will see that the properties that are linked to your databse contain a ColumnAttribute. See this code snippet:

[Column(Storage="_id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int id
{ …

[Column(Name="name", Storage="_name", DbType="VarChar(150) NOT NULL", CanBeNull=false)]
public string name
{ …

Here you see that de database field type is specified in the DbType attribute field. So that is wat we want to know in our code. We just have to find an easy way for getting this information. For this I created a Reflection Utility class. Here is the code:

public static class ReflectionUtility
{
    public static string GetPropertyName<T>(Expression<Func<T>>  expression)
    {
        return ((MemberExpression)expression.Body).Member.Name;
    }
    public static ColumnAttribute GetColumnAttribute<T>(Expression<Func<T>> expression)
    {
        string propertyName = ((MemberExpression)expression.Body).Member.Name;
        Type type = ((MemberExpression)expression.Body).Member.ReflectedType;
        PropertyInfo memberInfo = type.GetProperty(propertyName, BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        object[] attributes = memberInfo.GetCustomAttributes(typeof(ColumnAttribute), false);
        foreach (var attribute in attributes)
        {
            var columnAttribute = attribute as ColumnAttribute;
            if (columnAttribute != null) return columnAttribute;
        }
        return null;
    }
    public static string GetDbType<T>(Expression<Func<T>> expression)
    {
        ColumnAttribute attribute = GetColumnAttribute(expression);
        return (attribute != null) ? attribute.DbType : null;
    }
}

As you can see getting the information can easilly be done with some simple reflection. I even made sure you could query both public and non public properties (internal). After you added the ReflectionUtility class to your solution you can get the DbType of a property or just the name of a property with one simple line of code. Her is a sample of how you can use it:

string fieldName = ReflectionUtility.GetPropertyName(() => (new user()).id);
string dbType = ReflectionUtility.GetDbType(() => (new user()).name);

As you can see you only need one simple line of code for getting the database type information from a property. I am not even using ‘magic strings’ for doing the reflection. I just pass the property itself to the method. The bennefit of this is that after a refactoring (changing the name of a property) you don’t even have to try to find all the property name string and replace them by the new name.

There is one drawback for getting the field type information this way. It is possible to enter something in your .dbml that is different from the actual field type in the database. For instance you could set the size smaller than the actual field size.

Conclusion:

This was a fun exersize. If you think that the DbType information in your .dbml is good, then using this utility class is a very easy way to get the type information. There are a couple of things that could be done for improving this code. For instance you could parse the field type string into an object or you could make a validator method that wil check if the current value is not longer that the field length.

Did you ever have a method that returned a generic list of some type but you actually needed a generic list of one of its interfaces or base class? You probably solved this by cloning the method or by creating a new list while looping through all items. In the article below I will show you a nice and simple generic solution for this problem.

Let’s assume you have a class named Car that has an interface named IVehicle and you also have a class named Plane that also has the interface IVehicle. We also have a data repository that has a method for each of them for retrieving a list of items. Now we want to execute the IVehicle method named Move on all Car objects and Plane objects. We will start by retrieving both lists from our data repository object named MyRepository:

    var cars = MyRepository.GetCars()
    var planes = MyRepository.GetPlains()

Wouldn’t it be nice if we could just concatenate those 2 lists so that we could call the IVehicle method for all of them in one simple loop?

    var vehicles = cars.Concat(planes);
    foreach(var vehicle  in vehicles)
    {
        vehicle.Move();
    }

Unfortunately trying this will give you this error:
Error 1 The type arguments for method ‘System.Linq.Enumerable.Concat(System.Collections.Generic.IEnumerable, System.Collections.Generic.IEnumerable)’ cannot be inferred from the usage. Try specifying the type arguments explicitly.

If we do want to Concat the two collections together, then we first have to cast both collections to th IVehicle interface. At this moment C# 3.0 does not have a simple option to convert a generic list to one of its interfaces or base classes. The .ConvertAll is not easy to use. Fortunately Microsoft recognized this missing feature and in C# 4.0 you will be able to perform this cast by using Covariance and Contravariance. For now you have to use the difficult .ConvertAll method. The simple helper class below will make this easy for you.

    public static class GenericListConverter
    {
        public static T2 AsType<T1, T2>(this T1 model) where T1 : T2
        {
            return model;
        }
        public static IList<T2> ToListOfType<T1, T2>(this IEnumerable<T1> myList) where T1 : T2
        {
            return (new List<T1>(myList.ToList())).ConvertAll<T2>(AsType<T1, T2>);
        }
        public static IList<T2> ToListOfType<T1, T2>(this IList<T1> myList) where T1 : T2
        {
            return (new List<T1>(myList)).ConvertAll<T2>(AsType<T1, T2>);
        }
    }

Using this class is simple. You can just perform a ToListOfType on any generic IEnumerable or IList.

    var cars = myRepository.GetCars().ToListOfType<Car, IVehicle>();
    var planes = myRepository.GetPlains().ToListOfType<Plain, IVehicle>();

The result of this is that you have 2 generic lists of IVehicle and the Concat will now work.

In this case there is an alternative to the above helper class. It is possible to create a helper method that accept anything that implements the IVehicle interface. The code would then look something like:

    ...
        Move((List<Car>)cars);
        Move((List<Plane>)planes);
    ...
    public static void Move<TItem>(List<TItem> vehicles) where TItem : IVehicle
    {
        foreach (var vehicle in vehicles)
        {
            vehicle.Move();
        }
    }