29

実行時に、何らかのタイプのボックス化されたインスタンスを取得します。基になるタイプにボックス化解除する方法は?

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; 
4

8 に答える 8

23

コンパイル時にタイプがわからない場合は、それを置く場所がないため、ボックス化を解除できません。できることはobject、ボックス化された に格納することだけです。

のような参照型にも同じことが当てはまりますstring。コンパイル時に型がわからない場合は、正しい型にキャストできません。置く場所がありません。

たとえば、次のように、いくつかのタイプを特殊化できます。

if(obj is int) {
    int i = (int)obj;
    ...
} ...

時々 (あまり頻繁ではない) 役立つもう 1 つのトリックは、 genericsに切り替えることです。の観点から話す代わりに、 の観点からobject話しているのですT。ただし、これには... 用途が限られています。これを行う最も簡単な方法は、次のようにdynamicを使用することです。

dynamic obj = ...
Foo(obj);
...
Foo<T>(T val) { ... code with T ... }

そのアプローチに特別なケースを追加することもできます。

Foo(string val) { ... code with string ...}
Foo(int val) { ... code with int ...}

ただし、率直に言って、自分がやろうとしていることをよく見たほうがよいかもしれません。

于 2013-03-22T07:47:58.987 に答える
10

ここで、実際のボクシングが発生したとします。

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

代用する場合は、次のように注意してください。

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

Console.WriteLine (convertedBack); //it still prints 5
Console.WriteLine (o); //it even print 5 here

その理由は、基になるオブジェクトがまだint. この例を使用して、ここではボクシングは無関係であることを示しました。操作では抽象化に依存する必要があり、int動的にキャストする場合は、どの参照型を使用しますか。

于 2013-03-22T07:45:30.787 に答える
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);
    }
}
于 2013-03-22T08:31:19.313 に答える
1

式を使用:

var y = DynamicCast(obj, desiredType);

static object DynamicCast(object source, Type type)
{
    var parameter = Expression.Parameter(typeof(object), "input");

    var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object));

    var lambda = Expression.Lambda<Func<object, object>>(cast, parameter);

    var func = lambda.Compile();

    return func(source);
}
于 2016-12-08T08:18:08.000 に答える
0
public static string GetType(object data)
{
    Type type = data.GetType();
    return Convert.ChangeType(data, type).GetType().Name;
}

こんにちは、このメソッドはオブジェクト データを受け取り、オブジェクトの文字列型名を返します。これがあなたが必要とするものであることを願っています。

于 2016-03-24T07:45:26.340 に答える
-1

動的ランタイムを使用して試すことができます

    [Test]
    public void Test_UnboxingAtRuntime()
    {
        object boxed = "Hello";

        //this line is commented out as it does not compile
        // OverloadedMethod(boxed);

        var result = CallCorrectMethod(boxed);
        Assert.That(result, Is.EqualTo("string"));

        boxed = 1;
        result = CallCorrectMethod(boxed);
        Assert.That(result, Is.EqualTo("int"));
    }

    public string CallCorrectMethod(dynamic t)
    {
        return OverloadedMethod(t);
    }

    public string OverloadedMethod(string s)
    {
        return "string";
    }

    public string OverloadedMethod(int s)
    {
        return "int";
    }
于 2013-03-22T08:01:11.470 に答える