Sunday, August 19, 2007

Converting a List to an Array and back using Generics

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/converting_a_list_to_an_array_and_back_using_generics.htm]

UPDATE (8/21/2007): A comment from Martin shows that you can actually do this much simpler, using standard .Net constructors and methods. So, this code snippet is now just an example showing some features of Generics.

 

I love Generics in C# 2.0 because they let you abstract out type, which lets you code at a greater level of reusability. For example, you could use Generics to abstract out return type. You could also use Generics for standard set and conversion operations.

 

Say your code juggles between System.Collections.Generic.List and arrays. Lists are great for adding and removing items; arrays are just ubiquitous. You could easily write a converter utility methods to handle this:

 

    public static List ConvertArrayToList(T[] myArray)
    {
      if (myArray == null)
        return null;

      List myList = new List();

      for (int i = 0; i < myArray.Length; i++)
      {
        myList.Add(myArray[i]);
      }
      return myList;
    }

    public static T[] ConvertListToArray(List myList)
    {
      if (myList == null)
        return null;

      T[] myArray = new T[myList.Count];

      for (int i = 0; i < myArray.Length; i++)
      {
        myArray[i] = myList[i];
      }
      return myArray;
    }

 

Here we use the generic 'T' to abstract out an input value, the return type, and even to create a new object within the method. It's obviously much better than writing custom converter methods for all your object collections, or every using the ArrayList and unboxing.

 

Here's a simple unit test that shows how to call each method. It round-trips between the two - i.e. you should be able to convert from a list to an array and back to a list, and the final list should match the original one.

 

    [TestMethod]
    public void Convert_ListToArrayRoundTrip_1()
    {
      string[] astr = new string[] { "a", "bb", "ccc" };
      List<string> lstr = MyClass.ConvertArrayToList<string>(astr);

      string[] astr2 = MyClass.ConvertListToArray<string>(lstr);

      Assert.AreEqual(astr.Length, astr2.Length);
      Assert.AreEqual(astr[0], astr[0]);
    }

 

Besides convert methods, you could also write simple set methods, like something to remove all the items from a list:

 

    public static List RemoveItems(List mainList, List itemsToRemove)
    {
      if (mainList == null)
        return null;

      if (itemsToRemove == null || itemsToRemove.Count == 0)
        return mainList;

      for (int i = 0; i < itemsToRemove.Count; i++)
      {
        mainList.Remove(itemsToRemove[i]);
      }
      return mainList;
    }

 

You could write a test for the basic case:

 

    [TestMethod]
    public void RemoveItems_Some()
    {
      List<int> iMain = new List<int>();
      iMain.AddRange(new int[] { 10, 20, 30, 40, 50 });

      List<int> iRemove = new List<int>();
      iRemove.AddRange(new int[] { 30, 50, 70 });

      List<int> iFinal = MyClass.RemoveItems<int>(iMain, iRemove);

      Assert.AreEqual(3, iMain.Count);
      Assert.AreEqual(10, iMain[0]);
      Assert.AreEqual(20, iMain[1]);
      Assert.AreEqual(40, iMain[2]);
    }

 

Disclaimer: obviously you could have a lot more unit tests to fully test these methods.

 


Living in Chicago and interested in working for a great company? Check out the careers at Paylocity.

 

No comments:

Post a Comment