zoukankan      html  css  js  c++  java
  • C# 反射结构体struct的一个坑

    今天代码用到了反射赋值,代码是这样写的:

    1 var objtype = obj.GetType();
    2 var Fieldinfo = objtype.GetField("I64");
    3 Fieldinfo.SetValue(obj, 100L);

    当用户传进来的obj是class的时候无问题.但是传进来struct的时候,即不报错也不提示,但却什么值都没赋上!

    经过多番查询.直到看到这个关于struct和class的区别:

    http://www.cnblogs.com/gsk99/archive/2011/05/20/1904552.html

    和这个装箱/拆箱的说明:

    http://www.cnblogs.com/huashanlin/archive/2007/05/16/749359.html

    其中有一段:

    6:装箱/拆箱的内部操作。 
    装箱: 
    对值类型在堆中分配一个对象实例,并将该值复制到新的对象中。按三步进行。 
    第一步:新分配托管堆内存(大小为值类型实例大小加上一个方法表指针和一个SyncBlockIndex)。 
    第二步:将值类型的实例字段拷贝到新分配的内存中。 
    第三步:返回托管堆中新分配对象的地址。这个地址就是一个指向对象的引用了。 
    有人这样理解:如果将Int32装箱,返回的地址,指向的就是一个Int32。我认为也不是不能这样理解,但这确实又有问题,一来它不全面,二来指向Int32并没说出它的实质(在托管堆中)。 
    拆箱:
    检查对象实例,确保它是给定值类型的一个装箱值。将该值从实例复制到值类型变量中。 
    有书上讲,拆箱只是获取引用对象中指向值类型部分的指针,而内容拷贝则是赋值语句之触发。我觉得这并不要紧。最关键的是检查对象实例的本质,拆箱和装箱的类型必需匹配,这一点上,在IL层上,看不出原理何在,我的猜测,或许是调用了类似GetType之类的方法来取出类型进行匹配(因为需要严格匹配)。

    我看了看我调用的:SetValue方法.第一个参数是个object,是引用类型,也就是说,当我调用的时候,其实net把我的struct复制了一份,然后在新的那份改了值,我这边这份当然是没有被动过的.

    原因找到了,解决也就不难了,解决方案1:

    在调用SetValue之前,就把我的struct转成object,然后调用完再转回来:

     1     public struct MyStruct
     2     {
     3         public int TestInt;
     4     }
     5 
     6     class Program
     7     {
     8         static void Main(string[] args)
     9         {
    10             var Mystruct = new MyStruct();
    11             Type myType = typeof(MyStruct);
    12             FieldInfo myFieldInfo = myType.GetField("TestInt");
    13             Object someBoxedStruct = Mystruct;
    14             myFieldInfo.SetValue(someBoxedStruct, 1);
    15             MyStruct someUnBoxedStruct = (MyStruct)someBoxedStruct;
    16         }
    17    }

    尝试了一下,是可以的.

    还有一种方法,偶然搜索到的,把写入那部分改成这样:

    1 FieldInfo fi = typeof(T).GetField(name, BindingFlags.Public | BindingFlags.Instance);
    2 TypedReference reference = __makeref(obj);
    3 fi.SetValueDirect(reference, x);

    也是可以的.

  • 相关阅读:
    js判断时间间隔
    redis 常用命令
    Spring 启动 自动调用方法的两种形式
    多线程的异常处理
    多线程Monitor.TryEnter(有一个聪明的员工找老板。看到老板们在里面都掐成一团乱麻了,算了我还是撩吧)
    多线程中多个join的执行过程
    多线程之向线程传递参数
    ASP.Net Core下的安全(授权、身份验证、ASP.NET Core Identity)
    C# 中常用的索引器(转)
    《戏班的故事》C#基础之多线程之“前台线程-后台线程”
  • 原文地址:https://www.cnblogs.com/DragonStart/p/7482627.html
Copyright © 2011-2022 走看看