Practical Programming Pearls For .NET Developers

 (How)
C^# You Are - 10 August 2008 

This week I'm going to ask some questions I've gleaned from the forums, for the most part.

  1. You have a string of integer values separated by commas.  You want to create an array of integers.  How can you do it?  Answer

    The Array.ConvertAll method can be used to convert an array of one type to an array of another.  Here is an example

    int[] ConvertToArray ( string value )
    {
       string[] values = value.Split(',');

       int[] numbers = Array.ConvertAll<string, int>(values, Int32.Parse);
       return numbers;
    }

    The second parameter is a delegate that converts from the source type to the destination type.

  2. You have a string of integer values separated by commas.  You want to sum up the integral values.  How do you do it?  Answer

    A simple foreach loop would do.  However we can do it using the Array.ForEach method as well.

    int SumIt ( string value )
    {
       int[] values = ConvertToArray(value);

       Summation sum = new Summation();
       Array.ForEach(values, sum.Sum);
       return sum.Value;
    }

    struct Summation
    {
       private int m_Sum = 0;
       public void Sum ( int value )
       {
          m_Sum += value;
       };
       public int Sum { get { return m_Sum; } }
    }

    For summation this method is overkill but it can be useful when you need to enumerate an array and manage quite a bit of enumeration data.

  3. You want to create a generalized type conversion function.  How can you do it? (Forums)  Answer

    You don't technically need to.  .NET already has this functionality.  For conversions between plain old data types (ints, floats, etc) you can use Convert.ChangeType.  For more complex conversions you might need to upgrade to TypeConverter.  This class is used internally in .NET for type conversion. 

    Here's a simple generic method to convert from one type to another.  It does no error checking and will not work for complex types.  It will, however, convert to structure types in most cases.

    static TOutput ConvertTo <TInput, TOutput> ( TInput input )
    {
       Type typeIn = typeof(TInput);
       Type typeOut = typeof(TOutput);

       if (typeIn.IsPrimitive && typeOut.IsPrimitive)
          return (TOutput)Convert.ChangeType(input, typeOut);

       TypeConverter conv = TypeDescriptor.GetConverter(typeOut);
       return (TOutput)conv.ConvertFrom(input);
    }

  4. You need to allocate a multidimensional fixed size array for unmanaged interop.  You create the following structure but it doesn't work.  How can you create a multidimensional fixed size array?(forums)  Answer

    [StructLayout(LayoutKind.Sequential)]
    struct InteropData
    {
       int totalElements;
       fixed byte Elements[10, 20]; // Compiler error
    }

    You can't.  The fixed keyword does not support multidimensional arrays.  Instead you have to convert the array to a single dimension.  This is easily done by multiplying the rows by the columns.  The marshaler will translate the data correctly.

    [StructLayout(LayoutKind.Sequential)]
    struct InteropData
    {
       int totalElements;
       fixed byte Elements[10 * 20];  //Treat as a single dimension
    }

  5. How can you finalize a static class?(forums)  Answer

    You can't.  There is no such thing as either a finalizer or a destructor for static classes. 

    Remember that a finalizer/destructor is called only when the GC finds that an instance of the object is no longer referenced.  Static classes have no instances.  Therefore the GC will never look at a static class.

    Sometimes you might want to clean up the resources from a static class.  A static class is only unloaded when the containing appdomain is unloaded.  Therefore to clean up the resources your only real choice is to handle the appdomain's unload event.  You would have to expose a method from the static class to allow you to clean up the resources.  Not a great solution, but it works.

  6. How do you create global variables in C#?(forums)  Answer

    C# does not support globals.  To get global equivalent you should store the "globals" as static members (properties preferably) of a static class.  This is as close to globals as you can get.

    Ideally though you should not create a Globals-specific class except in rare cases.  Instead you should store the "global" with the class that is related to it.  For example connection strings should probably be stored in the application settings while network timeout values should be stored with the network management class.  Exceptions do exist though.