Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在编译时不知道该类型的情况下,如何将对象从一个对象取消绑定到它包含的类型?_C#_Unboxing - Fatal编程技术网

C# 在编译时不知道该类型的情况下,如何将对象从一个对象取消绑定到它包含的类型?

C# 在编译时不知道该类型的情况下,如何将对象从一个对象取消绑定到它包含的类型?,c#,unboxing,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

在运行时,我得到某种类型的装箱实例。如何将其取消绑定到基础类型

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; 

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

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
,您希望使用什么引用类型。

如果您在编译时不知道该类型,那么您就不能取消装箱,因为您没有地方放置它-您所能做的就是将它存储在
对象中,这是:盒装的

这同样适用于引用类型,如
string
:如果在编译时不知道类型,则无法将其强制转换为正确的类型:您无处放置它

您可以选择几种特殊情况,例如:

if(obj is int) {
    int i = (int)obj;
    ...
} ...
dynamic obj = ...
Foo(obj);
...
Foo<T>(T val) { ... code with T ... }
另一个有时(不经常)有用的技巧是切换到泛型;然后,不是用
对象
说话,而是用
T
说话。这已经。。。但用途有限。最简单的方法是通过动态方式,例如:

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

但是,坦率地说,我建议最好仔细看看您正在尝试做什么。

您可以尝试使用动态运行时

    [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";
    }

在这种情况下,我将通过使用
字典来使用策略模式:

内部类程序
{
私有静态void Main(字符串[]args)
{
var something=新事物();
计算值(13);
计算值(DateTime.Now);
计算值(星期一,星期一);
Console.ReadKey();
}
}
内部类某物
{
私有静态字典策略;
静态某物
{
//准备所有可用的策略。
_策略=新字典();
_策略。添加(type of(int),ComputeInteger);
_添加(类型(日期时间),计算日期时间);
}
公共无效计算值(对象值)
{
行动;
//检查我们是否有匹配策略。
if(!\u Strategies.TryGetValue(value.GetType(),out action))
{
//如果不是,则记录错误、抛出异常等。
动作=日志未知类型;
}
//对给定值执行匹配策略。
作用(价值);
}
私有静态void ComputeDateTime(对象源)
{
//我们得到一个对象,但我们确信它将始终是一个日期时间。
var值=(日期时间)源;
WriteLine(“我们有一个日期时间:+value”);
}
私有静态void ComputeInteger(对象源)
{
//我们得到一个对象,但我们确信它将始终是int。
var值=(int)源;
WriteLine(“我们得到了一个整数:“+值”);
}
私有静态void LogUnknownType(对象源)
{
//我们该拿那个喝醉的水手怎么办?
var unknownType=source.GetType();
Console.WriteLine(“不知道如何处理”+unknownType.FullName);
}
}

下面是一个例子,说明您为什么要这样做:

class MyClass
{
   public int Id {get;set;}
   public string Name {get;set;}
   public decimal Val {get;set;}
}
int i = 0;
var myClassImp = new MyClass();
foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet
{
   var prop = typeof(MyClass).GetProperties().ElementAt(i++);
   // !!!!!! THROWS EXCEPTION  !!!!!!!
   prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null);
}

这是因为该值是一个已装箱的对象。。。在运行时,您不知道类型,因此必须取消绑定到prop.PropertyType,这是一个实用的解决方案;尝试直接使用TypeConverter,如果失败,请转换为字符串,然后再转换:-

private static T GetValueOfType<T>(this ManagementBaseObject MBO, String FieldName) {
    T lResult;

    try {
        Object lObj = MBO[FieldName];

        var lSrcType = lObj.GetType();
        var lDestType = typeof(T);

        if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) {
            lResult = (T)lObj;
            return lResult;
        }

        var lDestTC = TypeDescriptor.GetConverter(typeof(T));
        if (lDestTC.CanConvertFrom(lSrcType)) {
            lResult = (T)lDestTC.ConvertFrom(lObj);
        } else {
            var lSrcTC = TypeDescriptor.GetConverter(lSrcType);
            String lTmp = lSrcTC.ConvertToInvariantString(lObj);
            lResult = (T)lDestTC.ConvertFromInvariantString(lTmp);
        }
    } catch {
        lResult = default(T);
    }
    return lResult;
}
private static T GetValueOfType(此ManagementBaseObject MBO,字符串字段名){
T lResult;
试一试{
对象lObj=MBO[FieldName];
var lSrcType=lObj.GetType();
var lDestType=typeof(T);
if(lDestType.IsValueType&&lDestType.IsAssignableFrom(lSrcType)){
lResult=(T)lObj;
返回lResult;
}
var lDestTC=TypeDescriptor.GetConverter(typeof(T));
if(lDestTC.CanConvertFrom(lSrcType)){
lResult=(T)lDestTC.ConvertFrom(lObj);
}否则{
var lSrcTC=TypeDescriptor.GetConverter(lSrcType);
字符串lTmp=lSrcTC.ConvertToInvariantString(lObj);
lResult=(T)lDestTC.ConvertFromInvariantString(lTmp);
}
}抓住{
lResult=默认值(T);
}
返回lResult;
}
您好,此方法接收对象数据并返回对象的字符串类型名称。 希望这就是您所需要的。

使用表达式:

变量y=动态成本(obj,所需类型)

static object DynamicCast(对象源,类型)
{
var参数=表达式参数(typeof(object),“input”);
var cast=Expression.TypeAs(Expression.Convert(参数,类型),typeof(对象));
var lambda=Expression.lambda(强制转换,参数);
var func=lambda.Compile();
返回函数(源);
}

String
是一种引用类型,因此在转换为
object
值类型时不会发生装箱。对象有两种表示形式:未装箱表单和装箱表单。引用类型(比如
string
)总是以装箱的形式出现。这个字符串可能是个坏例子。但无论如何,怎么做?这里的目的是什么?您想用
y
做什么,但以前用
obj
做不到?@PaulKyrejto:您仍然可以这样做:
var instance=Activator.CreateInstance(currentProperty.ReflectedType);instance.GetType().GetProperties().Select(x=>x.GetValue(instance,null))好,但您已经在这里使用了整型。我需要的是smth,比如
var convertedback=(type)Convert.ChangeType(o,type)@PaulKyrejto语法问题放在一边:这对你有什么帮助?你现在可以用
convertedback
做什么,而当它是
object
时,你不能做什么?@marcgravel下一个问题是“如何找到我可以用一件东西做的所有事情t
public static string GetType(object data)
{
    Type type = data.GetType();
    return Convert.ChangeType(data, type).GetType().Name;
}
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);
}