简体   繁体   中英

Casting object to type into variable of said type known only at runtime

Can someone help me to understand why the below doesn't work?

void test(int i)
{
    Console.WriteLine("int");
}

void test(String s)
{
    Console.WriteLine("String");
}

void runMe()
{
    object obj = 1;
    Type t = typeof(int);
    test((t)obj);
}

You get a "The type or namespace name 't' could not be found" error.

Is there a way to make this work? I need to cast an object to a specific type known only at runtime, but all options I've found are simply converting the data but still storing them in an object.

Edit: Added some pseudo methods to give more context.

It looks like you're basically trying to perform dynamic dispatch. The way you're trying it won't work, because while you work with static typing, all overload resolution is performed at execution.

However, you can use dynamic typing for this instead, with the dynamic type. At that point, overload resolution is performed at execution time instead:

void Test(int i)
{
    Console.WriteLine("int");
}

void Test(String s)
{
    Console.WriteLine("String");
}

void RunMe()
{
    dynamic obj = 1;
    // The right overload is picked at execution time
    Test(obj);
}

That will accomplish what you've shown in your question - but it's not necessarily the best approach. If you can possibly stick to static typing (without using reflection) I would do so. If you can only handle a known set of types, you might want to keep a Dictionary<Type, Action<object>> or something like that... although you then need to consider awkward things like subtyping etc.

If you do use dynamic typing, I'd try to use it for just a small piece of your code. As soon as you can get back "out" of dynamic typing, do so (eg by casting the result of a dynamically-bound call to its expected return type).

Here's an example with a few ways to do it combined into one example.

First method is to overload your method for supported types (these can get called directly when type is known at compile-time) and create a catch-all default overloaded method with parameter of type object which internally checks for supported types and calls the appropriate type-specific method (this is for types only known at run-time).

Second method can be used as an extension to the first, but you can also implement just the second method and skip the first part. Since you know the type at the start of the run-time and the type is not expected to change with each call, you can skip the per-call type checking and instead do a check once when you load the config, then set the appropriate delegate.

try it: https://dotnetfiddle.net/06JYE1#

using System;

public class Program
{
    public static void Main()
    {       
        var p = new Program();

        object s = "Hi";
        object i = 42;
        object f = 3.14;

        p.Test(s);
        p.Test(i);
        p.Test(f);

        p.SetTestType(GetConfigType());

        p.ConfiguredTest("Hello");
        p.ConfiguredTest(s);
    }

    public static Type GetConfigType() { return typeof(string); }



    Action<object> ConfiguredTest;

    void SetTestType(Type type)
    {
        if (type == typeof(string))
            ConfiguredTest = o => Test((string)o);

        else if (type == typeof(int))
            ConfiguredTest = o => Test((int)o);

        else
            ConfiguredTest = null;
    }

    void Test(object o) // catch-all when type is not known until runtime
    {
        if (ConfiguredTest != null)
        {
            ConfiguredTest(o); // if type is configured, we can skip type checking
        }
        else // if type is not configured, check for supported types
        {
            if (o is string)
                Test((string)o);

            else if (o is int)
                Test((int)o);

            else
                Console.WriteLine("Unsupported type: " + o.GetType());
        }
    }

    void Test(int i) { Console.WriteLine("Int = " + i); }

    void Test(String s) { Console.WriteLine("String = " + s); }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM