当前位置: 首页 > news >正文

服务器可以放几个网站/搜索引擎在线观看

服务器可以放几个网站,搜索引擎在线观看,网站制作服务热线,惠水县政府网站建设静态属性赋值先来看 Reflector反射出的IL源码(感谢Moen的提示),这次用 Release模式编译,去掉那些无用的辅助指令 public void AAA(string s) {MyClass.Name s; } .method public hidebysig instance void AAA(string s) cil managed {.maxstack 8//L_0000: ldarg.1 //这个是真…
  • 静态属性赋值

先来看 Reflector反射出的IL源码(感谢Moen的提示),这次用 Release模式编译,去掉那些无用的辅助指令

public void AAA(string s)
{MyClass.Name = s;
}
.method public hidebysig instance void AAA(string s) cil managed
{.maxstack 8//L_0000: ldarg.1 //这个是真正反射出的内容,但是理论上 这里应该是ldarg.0//下面一行是我特意修改的,上面的现象我无法解释,请知道的朋友也可以告知一二L_0000: ldarg.0//参数0,也就是string s这个参数推送的堆栈上 L_0001: stsfld string blqw.IL.Demo.MyClass::Name//使用当前堆栈上最近的一个参数,执行静态字段赋值指令,L_0006: ret //方法结束
}

  • 小贴士:

每个操作系统都会从堆栈中获取指定数量的参数,比如上一篇中的静态字段/属性取值操作,这个操作不需要用到任何参数,比如执行一个方法,这个方法签名有几个参数,就需要提供几个参数,再比如执行一次比较,需要提供2个参数等等,每个操作需要的参数都是事先就指定好的

再来看C#中的代码:

public static Action<string> ILTest()
{var dm = new DynamicMethod("", null, new[] { typeof(string) }, typeof(MyClass));var il = dm.GetILGenerator();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Stsfld, typeof(MyClass).GetField("Name"));il.Emit(OpCodes.Ret);return (Action<string>)dm.CreateDelegate(typeof(Action<string>));
}

 

 进行一些测试

static void Main(string[] args)
{var act = ILTest();MyClass.Name = "111";Console.WriteLine(MyClass.Name);act("aaaaa");Console.WriteLine(MyClass.Name);
}
测试方法
111
aaaaa
请按任意键继续. . .
测试结果

 

静态属性赋值

public static Action<string> ILTest()
{var dm = new DynamicMethod("", null, new[] { typeof(string) }, typeof(MyClass));var il = dm.GetILGenerator();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Call, typeof(MyClass).GetProperty("Name").GetSetMethod());il.Emit(OpCodes.Ret);return (Action<string>)dm.CreateDelegate(typeof(Action<string>));
}
  • 类型转换

之前看的栗子都是方法参数类型和属性字段类型相同的情况下的赋值,那么如果类型需要转换呢?

比如这样: 将MyClass的Name属性的类型改为int

class MyClass
{public static int Name { get; set; }
}

 

然后把要生成的方法改为传入Object类型的参数进行复制,但是在调用的时候依然传入int

static void Main(string[] args)
{var act = ILTest();act(222);
}public static Action<object> ILTest()
{var dm = new DynamicMethod("", null, new[] { typeof(object) }, typeof(MyClass));var il = dm.GetILGenerator();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Call, typeof(MyClass).GetProperty("Name").GetSetMethod());il.Emit(OpCodes.Ret);return (Action<object>)dm.CreateDelegate(typeof(Action<object>));
}

 

 

注意加了下划线的几个地方

再来看运行结果

static void Main(string[] args)
{var act = ILTest();MyClass.Name = 111;Console.WriteLine(MyClass.Name);act(222);Console.WriteLine(MyClass.Name);
}
测试代码
111
50310368
请按任意键继续. . .

 

虽然程序没有抛出异常,但是结果确错了...

其实这个时候IL相当于生成了一个这样的方法

public void AAA(object i)
{MyClass.Name = i; //编译器在这里就报错了
}

 

如果这个方法你是在VS中写的,那么在编译的时候编译器就告诉你这样写是错误,并且中断你的程序编译

编译器希望你改成这样

public void AAA(object i)
{MyClass.Name = (int)i;//增加类型转换 
}

 

虽然这样写,在传入参数错误的情况下也会抛出异常,但是这是运行时的错误,就跟程序本身没关系了

所以IL代码也需要加一个转换的操作

public static Action<object> ILTest()
{var dm = new DynamicMethod("", null, new[] { typeof(object) }, typeof(MyClass));var il = dm.GetILGenerator();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Unbox_Any, typeof(int));//加上这一句拆箱操作il.Emit(OpCodes.Call, typeof(MyClass).GetProperty("Name").GetSetMethod());il.Emit(OpCodes.Ret);return (Action<object>)dm.CreateDelegate(typeof(Action<object>));
}

 

再来看运行结果

 

好了,这回就对了

  • 重点:

别看我们在C#代码中类型转换操作都是一样的(Type)Object,但是在IL中值类型和引用类型会被编译成不同的指令,原因就是大家都知道的,值类型和引用类型的储存方式和位置不同引起的

object转值类型被称为拆箱,对应指令是OpCodes.Unbox_AnyOpCodes.Unbox(我不知道区别,一般都是用OpCodes.Unbox_Any)

object转引用类型就是强转,对应指令是OpCodes.Castclass

上面2个指令都需要提供一个指令参数,如il.Emit(OpCodes.Castclass, typeof(int));表示拆箱后的类型,或强转后的类型

值类型转为object称为装箱,对应指令是OpCodes.Box,不需要提供指令参数

引用类型转object,也是强转,对应指令是OpCodes.Castclass

所以其实我们昨天的栗子中有一部分也是需要改正的,在获取静态属性和字段值的时候,返回值的object,但是IL中没有进行转换

public static Func<object> ILTest()
{//编译li动态方法//1.声明动态方法对象DynamicMethod//  第一个参数是方法名,可以为空字符,不可以是null//  第二个参数是动态方法返回值类型//  第三个参数是Type[],表示方法参数,如果没有参数可以是null//  第四个参数是声明逻辑关联类,可以让动态方法访问该类有权访问所有字段,包括逻辑关联类的私有字段var dm = new DynamicMethod("", typeof(object), null, typeof(MyClass));//2.声明il编译器var il = dm.GetILGenerator();//3.执行MyClass类的Name属性的Get方法 这句对应刚才的L_0001il.Emit(OpCodes.Call, typeof(MyClass).GetProperty("Name").GetGetMethod());//4.方法结束,这句对应刚才的L_000a
    il.Emit(OpCodes.Ret);//5.由il编译器创建指定类型的动态方法委托return (Func<object>)dm.CreateDelegate(typeof(Func<object>));
}
昨天的栗子

 

修改后就应该变成这样:

public static Func<object> ILTest()
{var dm = new DynamicMethod("", typeof(object), null, typeof(MyClass));var il = dm.GetILGenerator();var MyClass_Name = typeof(MyClass).GetProperty("Name");il.Emit(OpCodes.Call, MyClass_Name.GetGetMethod());if (MyClass_Name.PropertyType.IsValueType)//判断属性类型是否是值类型
    {il.Emit(OpCodes.Box);//如果是值类型就装箱
    }else{il.Emit(OpCodes.Castclass, typeof(object));//引用类型就强转为object
    }il.Emit(OpCodes.Ret);return (Func<object>)dm.CreateDelegate(typeof(Func<object>));
}

 

  • 转型的注意事项

在转型虽然不是必须的,但最好是带上,不然你不知道什么时候会出现一些莫名其妙的错误

比如下面这个栗子:

错误的栗子

当把强转加上之后

虽然会导致程序异常,但至少比刚才那种情况好多了不是吗

  • 下篇预告

实例属性/字段的读取与设置,及其实用价值

转载于:https://www.cnblogs.com/blqw/p/3258768.html

http://www.jmfq.cn/news/4926637.html

相关文章:

  • 怎么做本地婚姻介绍网站/山西网络营销seo
  • 网页设计图片的代码/seo中文
  • 刷赞网站建设/免费推广软件下载
  • minecraft做图网站/php开源建站系统
  • 优秀高端网站建设公司/网站推广优化公司
  • 广告网站设计怎么样/100大看免费行情的软件
  • 网站备案系统验证码出错的解决方案/网站设计开发网站
  • 域名自助服务平台/小璇seo优化网站
  • 宿迁做网站 宿迁网站建设/中国互联网公司排名
  • 网络公司发生网站建设费分录/湖南关键词优化快速
  • 织梦m网站伪静态/北京网站建设公司案例
  • 中国住建网查询证书/郑州seo
  • 电商网站开发设计方案/整站seo服务
  • wordpress建站 ftp/品牌词优化
  • 湖北省最新疫情情况/优化网站页面
  • 网站开发过程记录/nba最新消息
  • 如何免费建网站/关键词排名优化顾问
  • 社区网站制作/今天最新新闻摘抄
  • 网站设计酷站/百度关键词怎么做
  • asp.net网站开发上/万网域名注册
  • 同一网站相同form id/seo主要做什么
  • 网站建设gzzhixun/国内可访问的海外网站和应用
  • 郑州做网站推广运营商/网络营销推广方式包括
  • 做网站的公司怎么找客户/友情链接软件
  • 苏州现在能正常出入吗/重庆网站优化软件
  • 四川销售应用app/站长工具 seo查询
  • 深圳做网站的公司排名/火狐搜索引擎
  • 做网站的职位叫什么问题/百度云网页版登录入口
  • b2b行业门户网站/怎样才能在百度上发布信息
  • 我买了一个域名怎么做网站/杭州百度推广代理商