Generics & Type Casting

I'm trying to write a generic method to sort 2-dimensional arrays. I'm converting each row in the array to a delimited string, which I then add to an ArrayList and then use the ArrayList.Sort() method.

The problem I'm having is in then casting the objects in the sorted ArrayList back to the original type.

This is the code:

Type type = typeof(T);

sortedArray[rowIndex, columnIndex] = (type) delimitedFields[columnIndex];

I'm getting this error:

The type or namespace name 'type' could not be found (are you missing a using directive or an assembly reference )

I can't work out what I'm missing.

I have the following using directives:

using System;

using System.Collections.Generic;

using System.Collections;

using System.Text;

using System.Reflection;

So I'm missing something... I just don't know what.



Answer this question

Generics & Type Casting

  • Googlesyrop

    Thanks for the replies. The struct constraint is what I'm after, but the problem I'm having now is casting from a string back to <T> the original type.

    So, in the test I am trying I take an array of ints, convert to strings to sort, but then I want to cast each string back to int.

    In order to do

    T obj = s as T;

    I need the "class" constraint. But I want to work with base value types only.

    So my options seem to be to work with objects only

    Or do I have implement the IConvertible interface and come up with my own ConvertToT method

    Help is much appreciated.


  • carthegenian

    I'm not aware of "OR"ing constraints, only "AND"ing.

    As a workaround, you could put add to your generic class method a System.Diagnostics.Debug.Assert() to check that T.GetType() is one of the allowed types.

    Brian


  • Liel

    In your sample code try changing the 2nd line in the method to "T temp = (T)s;", it should work. I did a simple test on similar lines by declaring a generic class with struct constraint:

    public class Class2<T> where T : struct< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

    {

        T secondVar;

        string strVar;

     

        public T Test(T firstVar)

        {

            strVar = firstVar.ToString();

            secondVar = (T)firstVar;

     

            return secondVar;

        }

    }

    Test() method simply did a convesion like you tried with a 2-D array. Finally I tested this code with a button on a form:

    Class2<int> obj = new Class2<int>();

    MessageBox.Show(obj.Test(5).ToString());

     


  • alshami

    You can't cast string to int because they are not compitable type. That's why int, double, DateTime etc have Parse method and you can pass in a string and extract data of the correct type. We can use this knowledge, and invoke the Parse method using the reflection. What I have done in CastTest class is wrote a private method to parse out the value from the string:

    public class CastTest<T> where T : struct

    {

    T newT;

    string s;

    public T Test(T item)

    {

    s = item.ToString();

    newT = Parse(s);

    return newT;

    }

    private T Parse(string s)

    {

    Type t = typeof(T);

    System.Reflection.MethodInfo parseMethod = t.GetMethod("Parse", new Type[] { typeof(string) });

    if (parseMethod != null)

    return (T)parseMethod.Invoke(null, new object[] { s });

    else

    throw new ApplicationException(t.Name + " type does not support Parse() method.");

    }

    }

    This was a very good learning exercise for me too.


  • GuyLowndes

    I only just spotted the error in your code - you're casting firstVar as T, but it is already T.
  • Sueva

    You are right, I don't know what I was thinking, sorry about that. I will keep thinking about this, in the mean time, instead of using a string type for "s", using an object type seems to let you cast back to the appropriate type.

    public class CastTest<T> where T : struct

    {

    T newT;

    object s;

    public T Test(T item)

    {

    s = item;

    newT = (T)s;

    return newT;

    }

    }


  • haal1

    To limit to only value types you can use struct constraint:

    yourclass<T> where T : struct


  • DOAHunterX

    How was "s" defined Isn't it is also of the generic type T Then you may not need the typecast. Can you please post a complete code snippet
  • jeremym1234

    Thanks - that's very helpful.

    I had considered the Parse method earlier on, but hadn't a clue where to start with writing a custom version of it. I thought that if it seemed too complicated there must have been an easier way to do it.

    However, this is very useful information.

    Thanks for all your help!

    James


  • bobiav

    No worries! Thanks for your continued attention.

    Of course I can compare objects, the original goal of this was get a 2d Array into an ArrayList (as a delimited string), sort it (with the necessary methods to sort by a certain column) then split out each string and add them back to the original T[,] Array.

    In any case, in the meantime I've written the QuickSort to work with 2d Arrays and sort by selected column - so as a learning exercise (which is all this is) it has certainly been useful.

    I'd be interested to know why you can't cast back to <T> from string. I wonder if it is because string is nullable

    Anyway, thanks for your help so far.

    James


  • clarayeung

    Thanks, but I can't get that to work - still get the Cannot convert "string" to "T" error.

    public class CastTest<T> where T : struct
    {
          T newT;
          string s;
         
          public T Test(T item)
          {
                s = item.ToString();
                newT = (T) s;
                return newT;
          }
    }
    public class Tester
    {
          static void Main()
          {
                int i = 5;
               
                CastTest<int> ct = new CastTest<int>();
               
                int j = ct.Test(i);
               
                Console.WriteLine(j.GetType().ToString());
          }
    }


  • Server Girl

    Thanks for the response. Unfortunately it doesn't work - I think because I know nothing about Generics and am having problems with constraints.

    I want restrict the 2-dimensional array to vase* value types only - so: int, string, double etc.

    It doesn't seem that this is possible. Any thoughts

    Thanks,

    James

    *edit: base, not vase


  • AlexTorone

    Type type = typeof(T);

    makes type a variable not a type.

    Try:

    sortedArray[rowIndex, columnIndex] = (T) delimitedFields[columnIndex];

    or a bit more elegantly:

    sortedArray[rowIndex, columnIndex] = delimitedFields[columnIndex] as T;


  • ArifKh

    Apologies, here you go:

    public void CastTest(T[,] tObject)

    {

    string s = tObject[0,0].ToString();

    T temp = s as T;

    tObject[0,0] = temp;

    }

    Where tObject is a 2d array of value types (so ints, doubles etc...)


  • Generics & Type Casting