10

This one has proven to be a little tricky for me so far. I am wondering if it is possible to type cast an object using a System.Type object.

I have illustrated below what I mean:

public interface IDataAdapter
{
    object Transform(object input);
    Type GetOutputType();
}

public class SomeRandomAdapter : IDataAdapter
{
    public object Transform(object input)
    {
        string output;

        // Do some stuff to transform input to output...

        return output;
    }

    public Type GetOutputType()
    {
        return typeof(string);
    }
}

// Later when using the above methods I would like to be able to go...
var output = t.Transform(input) as t.GetOutputType();

The above is a generic interface which is why I am using "object" for the types.

Ryall
  • 12,010
  • 11
  • 53
  • 77

5 Answers5

8

The typical way to do that is to use generics, like so:

public T2 Transform<T, T2>(T input)
{
    T2 output;

    // Do some stuff to transform input to output...

    return output;
}

int    number = 0;
string numberString = t.Transform<int, string>(number);

As you mentioned in your comment below, generics are very similar to C++ Templates. You can find the MSDN documentation for Generics here, and the article "Differences Between C++ Templates and C# Generics (C# Programming Guide)" will probably be helpful.

Finally, I might be misunderstanding what you want to do inside the method body: I'm not sure how you'll transform an arbitrary type T into another arbitrary type T2, unless you specify constraints on the generic types. For example, you might need to specify that they both have to implement some interface. Constraints on Type Parameters (C# Programming Guide) describes how to do this in C#.

Edit: Given your revised question, I think this answer from Marco M. is correct (that is, I think you should use the Converter delegate where you're currently trying to use your IDataAdapter interface.)

Community
  • 1
  • 1
Jeff Sternal
  • 47,787
  • 8
  • 93
  • 120
  • 1
    I didn't make it to clear in the example but the two methods are within an interface IDataAdapter. – Ryall Sep 03 '09 at 16:31
7

Why make it complicated, when you are sure that it returns a string?

var output = t.Transform(input) as string;

If I have misunderstood what you are saying, here is one more way

var output = Convert.ChangeType(t.Transform(input), t.GetOutputType());
shahkalpesh
  • 33,172
  • 3
  • 63
  • 88
  • 1
    Because the example is an interface - updating now. – Ryall Sep 03 '09 at 16:32
  • I'll Hit 1 for this! I like the idea of ``Convert.ChangeType()`` and providing the type of the object as 2nd argument so it will be changed to that type. I'm working on another library and hoping that this will save my night. Thanks @shahkalpesh – Allen Linatoc Aug 25 '15 at 14:15
3

You are better off using something like the Converter delegate

public delegate TOutput Converter<TInput, TOutput>(TInput input);

for an example, check out msdn

public static void Main()
{
    // Create an array of PointF objects.
    PointF[] apf = {
        new PointF(27.8F, 32.62F),
        new PointF(99.3F, 147.273F),
        new PointF(7.5F, 1412.2F) };

    // Display each element in the PointF array.
    Console.WriteLine();
    foreach( PointF p in apf )
        Console.WriteLine(p);

    // Convert each PointF element to a Point object.
    Point[] ap = Array.ConvertAll(apf, 
        new Converter<PointF, Point>(PointFToPoint));

    // Display each element in the Point array.
    Console.WriteLine();
    foreach( Point p in ap )
    {
        Console.WriteLine(p);
    }
}

public static Point PointFToPoint(PointF pf)
{
    return new Point(((int) pf.X), ((int) pf.Y));
}
Marco M.
  • 2,956
  • 2
  • 29
  • 22
  • How does this allow a Type object to cast another object? TInput and TOutput are not objects and need to be known at compile time. – Despertar Feb 18 '12 at 23:16
2

The above is a generic interface which is why I am using "object" for the types

Would it not make more sense to use an actual generic interface:

public U Transform<T, U>(T input)
{
    string output;

    return output;
}

U output = t.Transform(input) as U;
Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • These look like Templates from C++ - haven't actually covered them in C# yet. Thanks! – Ryall Sep 03 '09 at 16:24
  • I am a little confused as to how you are using 'U' outside of the generic. What scope are you given? – Ryall Sep 03 '09 at 16:25
  • @Kelix: "U" would be your actual type, you wouldn't really use "U" like that. Look at @Jeff's answer and notice his T2 is replaced by "string" and matches up in the same manner. – Ahmad Mageed Sep 03 '09 at 16:34
  • I could also use a 'var' and not cast at all if I am not mistaken? – Ryall Sep 03 '09 at 16:39
2

This is what I have gone with (based off the IEnumerable structure):

public interface IDataAdapter
{
    object Transform(object input);
}

public interface IDataAdapter<OutT, InT> : IDataAdapter
{
    OutT Transform(InT input);
}

public class SomeClass : IDataAdapter<string, string>
{
    public string Transform(string input)
    {
        // Do something...
    }

    public object Transform(object input)
    {
        throw new NotImplementedException();
    }
}
Ryall
  • 12,010
  • 11
  • 53
  • 77