Type Casting an Object using a “Type” Object in C#

2019-06-15 08:36发布

问题:

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.

回答1:

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.)



回答2:

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());


回答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));
}


回答4:

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();
    }
}


回答5:

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;