如何从对象中取消对它包含的类型,在编译时不知道该类型?

Pau*_*jto 26 c# unboxing

在运行时,我得到某种类型的盒装实例.如何将其拆箱到基础类型?

Object obj;
String variable = "Some text";

obj = variable // boxing;

// explicit unboxing, because we know the type of variable at compile time.

var x = (String)obj     

// Now let's pretend that we don't know the type of underlying object at compile time. 

Type desiredType = obj.GetType(); // But we can figure out.

//And now the question. 
//How to express something like this:

var y = (desiredType)obj; //Need to get unboxed instance of initial variable here; 
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 23

如果您在编译时不知道类型,那么您无法取消装箱,因为您无处可放 - 您可以做的就是将其存储在一个object,即:盒装.

这同样适用于以下引用类型string:如果在编译时不知道类型,则无法将其强制转换为类型:您无处可去.

可以使用几种类型的特例,例如:

if(obj is int) {
    int i = (int)obj;
    ...
} ...
Run Code Online (Sandbox Code Playgroud)

另一个有时(通常)有用的技巧是转换为泛型 ; 然后,而不是谈论object你的谈话T.这有......限制使用.最简单的方法是通过动态,例如:

dynamic obj = ...
Foo(obj);
...
Foo<T>(T val) { ... code with T ... }
Run Code Online (Sandbox Code Playgroud)

您还可以为该appreach添加特殊情况:

Foo(string val) { ... code with string ...}
Foo(int val) { ... code with int ...}
Run Code Online (Sandbox Code Playgroud)

但是,坦率地说,我建议你最好仔细看看你想做什么.


Ily*_*nov 9

现在让我们假设,真正的拳击发生:

int v = 5;

object o = v; //boxed 

Type type = o.GetType(); //will return typeof(int)

int convertedBack = (int)Convert.ChangeType(o, type);

Console.WriteLine (convertedBack); //prints 5
Run Code Online (Sandbox Code Playgroud)

备注,如果你替换:

object convertedBack = Convert.ChangeType(o, type);

Console.WriteLine (convertedBack); //it still prints 5
Console.WriteLine (o); //it even print 5 here
Run Code Online (Sandbox Code Playgroud)

原因是底层对象仍然存在int.我刚用这个例子告诉你,拳击在这里无关紧要.你需要在操作中依赖一些抽象,如果你想int动态转换,你想要使用哪种引用类型.

  • 抛开@PaulKyrejto语法问题:以什么*可能的方式对你有帮助?你现在可以做什么`convertback`,当它是`object`时你不能做什么? (3认同)
  • @MarcGravell 下一个问题将是_“如何找到我可以用我不知道类型的东西做的所有事情?”_... (2认同)

Oli*_*ver 5

在这种情况下,我将通过使用策略模式Dictionary<Type, Action<object>>

internal class Program
{
    private static void Main(string[] args)
    {
        var something = new Something();

        something.ComputeValue(13);
        something.ComputeValue(DateTime.Now);
        something.ComputeValue(DayOfWeek.Monday);

        Console.ReadKey();
    }
}

internal class Something
{
    private static Dictionary<Type, Action<object>> _Strategies;

    static Something()
    {
        // Prepare all available strategies.
        _Strategies = new Dictionary<Type, Action<object>>();
        _Strategies.Add(typeof(int), ComputeInteger);
        _Strategies.Add(typeof(DateTime), ComputeDateTime);
    }

    public void ComputeValue(object value)
    {
        Action<object> action;

        // Check if we have a matching strategy.
        if (!_Strategies.TryGetValue(value.GetType(), out action))
        {
            // If not, log error, throw exception, whatever.
            action = LogUnknownType;
        }

        // Perform the matching strategy on the given value.
        action(value);
    }

    private static void ComputeDateTime(object source)
    {
        // We get an object, but we are sure that it will always be an DateTime.
        var value = (DateTime)source;
        Console.WriteLine("We've got an date time: " + value);
    }

    private static void ComputeInteger(object source)
    {
        // We get an object, but we are sure that it will always be an int.
        var value = (int)source;
        Console.WriteLine("We've got an integer: " + value);
    }

    private static void LogUnknownType(object source)
    {
        // What should we do with the drunken sailor?
        var unknownType = source.GetType();
        Console.WriteLine("Don't know how to handle " + unknownType.FullName);
    }
}
Run Code Online (Sandbox Code Playgroud)