精华内容
参与话题
问答
  • Effective C# 摘要

    2006-04-16 22:02:00
    第一章 C#语言元素 项1:总是使用属性,不要使用可访问的数据成员 项2:常数项尽量使用readonly,而不是const 项3:类型装换时,不要使用强制转换,使用操作符is或者as 项4:使用Conditional标记代替#if条件编译 项5...
    第一章 C#语言元素 

    项1:总是使用属性,不要使用可访问的数据成员
    项2:常数项尽量使用readonly,而不是const
    项3:类型装换时,不要使用强制转换,使用操作符is或者as
    项4:使用Conditional标记代替#if条件编译
    项5:给你建立的每个类写一个ToString()函数
    项6:搞清楚值类型和引用类型的区别
    项7:尽量选择不可变基础类型
    项8:对于值类型保证0值代表一个有效的状态
    项9:理解ReferenceEquals()、静态Equals()、实例Equals()以及==操作符之间的区别
    项10:理解GetHashCode()的缺陷
    项11:尽量使用foreach循环

    第二章 .NET资源管理

    项12:用变量初始化语句,而不是赋值语句
    项13:使用静态构造函数初始化静态类成员
    项14:利用构造函数链
    项15:利用using语句和try/finally来释放资源
    项16:减少内存垃圾
    项17:减少装箱和拆箱
    项18:实现标准的Dispose模式

    第三章 用C#表达你的设计思想

    项19:定义和实现接口,而不是继承
    项20:搞清楚实现接口和重写虚拟函数的区别
    项21:用Delegate表达回调要求
    项22:用Event定义外发接口
    项23:避免返回类的内部对象的引用
    项24:尽量使用声明方式编程,而不是命令式编程
    项25:尽量使用Serializable类型
    项26:使用IComparable和IComparer接口实现可排序关系
    项27:避免实现ICloneable
    项28:避免实现类型转换操作符
    项29:不要使用new修饰符,除非基类的改变要求你使用它

    第四章 创建二进制组件

    项30:尽量创建符合CLS规格的程序集
    项31:尽量创建小而简单的函数
    项32:尽量创建小而且内聚的程序集
    项33:限制你创建的类型的可见性
    项34:创建Large-Grain(一次传送多个数据) Web调用接口

    第5章 使用.NET框架

    项35:尽量实现可继承的函数,而不是事件处理程序
    项36:有效地使用.NET运行时诊断函数
    项37:使用标准配置机制
    项38:利用和支持数据绑定
    项39:使用.NET验证机制
    项40:根据你的需要使用不同的Collection类
    项41:尽量使用DataSet,而不是自定义结构
    项42:使用属性来简化反射机制
    项43:不要过分使用反射机制
    项44:创建完整的应用程序专用的异常类

    第6章 其他

    项45:尽量使用强异常保证
    项46:尽量少地使用互操作方法(Interop)
    项47:尽量使用安全代码
    项48:关注开发工具和资源
    项49:为C#2.0做好准备
    项50:关注ECMA标准
    展开全文
  • Java和C#摘要算法实现

    千次阅读 2005-07-16 12:27:00
    一 问题由来对于Passport,微软解释道:Passport 是一种服务。利用该服务,用户可以通过只创建一个登录名和密码就能登录到 Microsoft Passport Network 站点和服务。...如果您通过移动电话访问 Passport 服务,

    一 问题由来

    对于Passport,微软解释道:Passport 是一种服务。利用该服务,用户可以通过只创建一个登录名和密码就能登录到 Microsoft Passport Network 站点和服务。通常来讲,当您在 Passport Network 上创建帐户时,Passport 只收集和存储用户名(通常是您的电子邮件地址)和密码,以创建您的凭据。如果您通过移动电话访问 Passport 服务,我们会要求您提供您的电话号码用作登录名,并要求您创建一个 PIN 用作您的密码。
    在注册时,Passport 将一个 64 位数字的唯一标识符 (ID) 与每个 Passport Network 帐户关联。当您选择登录到 Passport Network 站点时,Passport 将此独一无二的标识符加密并发送到该站点,便于该站点用其判断从一个登录会话转到另一个会话的人员是否是同一个人。

    二 微软的摘要算法

    与Passport类似的想法,两年前,也使用了类似方法来提供统一系统登录入口,这个服务是由java语言实现的,而系统中有些部分是用.Net技术实现,因此要保证这个服务具有良好的互操作性.
    在保证了服务实现遵循WS-I协议标准之后,遇到了如下问题:
    因密码都经过了哈希处理,java中的哈希和.Net中的哈希对于相同的串产生了不同的输出.这个问题令人印象深刻,所以把它记录了下来.今天把它贴出来供有需要的人们参考.
    以C#为例,首先看看.Net的哈希算法实现,
    HashAlgorithm 类,声明为
    public abstract class HashAlgorithm : ICryptoTransform, IDisposable
    表示所有加密哈希算法实现均必须从中派生的基类,目前,微软提供了派生自这个类的类包括:
          System.Security.Cryptography.KeyedHashAlgorithm
          System.Security.Cryptography.MD5
          System.Security.Cryptography.SHA1
          System.Security.Cryptography.SHA256
          System.Security.Cryptography.SHA384
          System.Security.Cryptography.SHA512
         
          它们都是抽象类,申明为:public abstract class MD5 : HashAlgorithm,其它依此类推.
          其中,KeyedHashAlgorithm为键控哈希算法的抽象类,微软提供了两个实现:
          System.Security.Cryptography.HMACSHA1
          System.Security.Cryptography.MACTripleDES
          键控哈希算法是依赖于密钥的单向哈希函数,用作消息验证代码。只有知道密钥的人才能验证哈希值。加密哈希算法提供没有机密的真实性。
          最后的实现,微软称为加密服务提供程序(CSP),例如MD5的CSP是MD5CryptoServiceProvider类.
          到这里,可以认为HashAlgorithm类及其实现形成了策略模式,加密服务提供者提供服务和修改服务不会影响客户代码.
          对于使用,有两种方式,一种是可直接创建的MD5 类的实例.如
          MD5 md5=new MD5CryptoServiceProvider();
          byte[] hashvalue=md5.ComputeHash(data2ToHash);
          另一种是利用CryptoConfig类访问加密配置信息来提供相应的算法.它支持很多加密算法:
          SHA,MD5,SHA256,SHA384,SHA512,RSA,DSA,DES,TripleDES,RC2,Rijndael.
          例如由加密配置系统返回的MD5 实例:
          byte[] hashvalue1 = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(data1ToHash);
          到这里CryptoConfig类和HashAlgorithm类及其实现形成了工厂方法模式,而CryptoConfig就是一个抽象工厂,用于创建不同的加密算法对象,客户代码通过CryptoConfig访问加密算法实现.
         
    三     java的哈希算法实现
          java.security.MessageDigest是一个工厂类,使用工厂方法getInstance即可获得不同的加密算法,并通过MessageDigest访问,例如:
          MessageDigest ha=MessageDigest.getInstance("SHA");
          MessageDigest ha=MessageDigest.getInstance("MD5");
          具体实现由算法服务提供者提供.在使用方面两种环境都比较简洁.
          
    四     测试两种环境下的摘要算法
          运行下面两个类即可了,类清单为:

    java代码:


    package security;

    import java.security.MessageDigest;
    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;

    /**
     *
     * <p>Title: </p>
     *
     * <p>Description:
     * 用于同C#语言实现的摘要算法对比.
     * </p>
     *
     * <p>Copyright: Copyright (c) 2005</p>
     *
     * <p>Company: </p>
     *
     * @author not attributable
     * @version 1.0
     */
    public class HACompareJC {
      public HACompareJC() {
      }

      public static void main(String[] args) throws Exception {
        HACompareJC hacomparejc = new HACompareJC();
        String data = "锐意";
        String ha = "SHA";
        System.out.println(hacomparejc.testHA1(data, ha));
        System.out.println(hacomparejc.testHA2(data, ha));
        System.out.println(hacomparejc.testHA3(data, ha));
      }

      /**
       * ??>}G?y????V=
       * @param data String
       * @throws Exception
       */
      public String testHA1(String data, String ha) throws Exception {
        byte[] buffer = data.getBytes("UTF8");
        MessageDigest messageDigest = MessageDigest.getInstance(ha);
        messageDigest.update(buffer);
        String s = new String(messageDigest.digest(), "UTF8");
        //System.out.println(s);
        return new String(s);
      }

      /**
       * 对哈希值使用base64编码.
       * sxjuhT59R/2peb2UtspWPQ==
       * @param data String
       * @throws Exception
       */
      public String testHA2(String data, String ha) throws Exception {
        byte[] buffer = data.getBytes("UTF8");
        MessageDigest messageDigest = MessageDigest.getInstance(ha);
        messageDigest.update(buffer);
        buffer = messageDigest.digest();
        String s = new sun.misc.BASE64Encoder().encode(buffer);
        //System.out.println(s);
        return s;
      }

      /**
       * 这个是和C#中的处理结果是相同的.
       * 4b-5d-11-c9-96-2d-62-92-b7-9b-60-e3-c9-a4-47-5c
       * @param data String
       * @return String
       */
      public String testHA3(String data, String ha) {
        MessageDigest m = null;
        try {
          m = MessageDigest.getInstance(ha);
          m.update(data.getBytes("gb2312"));
        }
        catch (NoSuchAlgorithmException ex1) {
        }
        catch (UnsupportedEncodingException ex) {
        }
        return toHex(m.digest());
      }

      /**
       * 把传来的字节数组取底8位转换到十六进制表示的字符串,并返回.
       * @param buffer byte[]
       * @return String
       */
      private String toHex(byte[] buffer) {
        String result = "";
        for (int i = 0; i < buffer.length; i++) {
          result += Integer.toHexString( (0x000000ff & buffer[i]) |
                                        0xffffff00).substring(6) + "-";
        }
        return result.substring(0, result.length() - 1);
      }

    }

    C#代码:


    using System;
    using System.IO ;
    using System.Security.Cryptography;
    using System.Text ;
    using System.ClassLibrary ;

    namespace endecrypt
    {
     /// <summary>
     /// HACompareJC 的摘要说明。
     /// 用于同java语言实现的摘要算法对比.
     /// </summary>
     public class HACompareJC
     {
      public HACompareJC()
      {
      }
      /// <summary>
      /// .% H]+4TW2&
      /// </summary>
      /// <param name="data"></param>
      /// <returns></returns>
      public static string testHA1(string data,string am)
      {
       byte[] buffer=Encoding.UTF8.GetBytes(data);
       //MD5 ha=new System.Security.Cryptography.MD5CryptoServiceProvider();
       HashAlgorithm ha=(HashAlgorithm) CryptoConfig.CreateFromName(am.ToUpper());
       buffer=ha.ComputeHash(buffer);
       return Encoding.UTF8.GetString(ha.ComputeHash(buffer));
      }
      /// <summary>
      /// 对哈希值使用base64编码.
      /// sxjuhT59R/2peb2UtspWPQ==
      /// </summary>
      /// <param name="data"></param>
      /// <returns></returns>
      public static string testHA2(string data,string am)
      {
       byte[] buffer=Encoding.UTF8.GetBytes(data);
       //MD5 ha=new System.Security.Cryptography.MD5CryptoServiceProvider();
       HashAlgorithm ha=(HashAlgorithm) CryptoConfig.CreateFromName(am.ToUpper());
       buffer=ha.ComputeHash(buffer);
       return Convert.ToBase64String (buffer);
      }
      /// <summary>
      /// 4b-5d-11-c9-96-2d-62-92-b7-9b-60-e3-c9-a4-47-5c
      /// </summary>
      /// <param name="data"></param>
      /// <returns></returns>
      public static string testHA3(string data,string am)
      {
       Encoding encode=Encoding.GetEncoding("gb2312");
       byte[] buffer=encode.GetBytes(data);
       //MD5 ha=new System.Security.Cryptography.MD5CryptoServiceProvider();
       HashAlgorithm ha=(HashAlgorithm) CryptoConfig.CreateFromName(am.ToUpper());
       buffer=ha.ComputeHash(buffer);
       return toHex(buffer);
      }

      /// <summary>
      /// 把传来的字节数组取底8位转换到十六进制表示的字符串,并返回.
      /// </summary>
      /// <param name="buffer"></param>
      /// <returns></returns>
      private static string toHex(byte[] buffer)
      {
       String result = "";
       for (int i = 0; i < buffer.Length; i++)
       {
        //result += Integer.toHexString((0x000000ff & buffer[i])|0xffffff00).substring(6) + "-";
        uint tm=UInt32.Parse(Convert.ToString((0x000000ff & buffer[i])|0xffffff00));
        result +=tm.ToString("x").Substring(6)+"-";
       }
       return result.Substring(0, result.Length - 1);
      }
      public static void Main()
      {
       string data="锐意";
       string ha="sHA1";
       string tm=HACompareJC.testHA1(data,ha);
       log.logs(tm);
       tm=HACompareJC.testHA2(data,ha);
       log.logs(tm);
       tm=HACompareJC.testHA3(data,ha);
       log.logs(tm);
      }
     }
    }

    通过在网络中传输到客户端的密码哈希值,同在内存中比较由登录用户提供的口令哈希值(或者是由在本地的系统将口令计算为哈希值,实际上那个系统就是采用了这种方式,才引出这个问题)来确定是否允许该用户进入系统.

    展开全文
  • Effective C# 摘要(全)

    2005-10-19 15:21:00
    Effective C# 第一章 C#语言元素 项1:总是使用属性,不要使用可访问的数据成员项2:常数项尽量使用readonly,而不是const项3:类型装换时,不要使用强制转换,使用操作符is或者as项4:使用Conditional标记代替#...

    Effective C#

    第一章 C#语言元素

    项1:总是使用属性,不要使用可访问的数据成员
    项2:常数项尽量使用readonly,而不是const
    项3:类型装换时,不要使用强制转换,使用操作符is或者as
    项4:使用Conditional标记代替#if条件编译
    项5:给你建立的每个类写一个ToString()函数
    项6:搞清楚值类型和引用类型的区别
    项7:尽量选择不可变基础类型
    项8:对于值类型保证0值代表一个有效的状态
    项9:理解ReferenceEquals()、静态Equals()、实例Equals()以及==操作符之间的区别
    项10:理解GetHashCode()的缺陷
    项11:尽量使用foreach循环

    第二章 .NET资源管理

    项12:用变量初始化语句,而不是赋值语句
    项13:使用静态构造函数初始化静态类成员
    项14:利用构造函数链
    项15:利用using语句和try/finally来释放资源
    项16:减少内存垃圾
    项17:减少装箱和拆箱
    项18:实现标准的Dispose模式

    第三章 用C#表达你的设计思想

    项19:定义和实现接口,而不是继承
    项20:搞清楚实现接口和重写虚拟函数的区别
    项21:用Delegate表达回调要求
    项22:用Event定义外发接口
    项23:避免返回类的内部对象的引用
    项24:尽量使用声明方式编程,而不是命令式编程
    项25:尽量使用Serializable类型
    项26:使用IComparable和IComparer接口实现可排序关系
    项27:避免实现ICloneable
    项28:避免实现类型转换操作符
    项29:不要使用new修饰符,除非基类的改变要求你使用它

    第四章 创建二进制组件

    项30:尽量创建符合CLS规格的程序集
    项31:尽量创建小而简单的函数
    项32:尽量创建小而且内聚的程序集
    项33:限制你创建的类型的可见性
    项34:创建Large-Grain(一次传送多个数据) Web调用接口

    第5章 使用.NET框架

    项35:尽量实现可继承的函数,而不是事件处理程序
    项36:有效地使用.NET运行时诊断函数
    项37:使用标准配置机制
    项38:利用和支持数据绑定
    项39:使用.NET验证机制
    项40:根据你的需要使用不同的Collection类
    项41:尽量使用DataSet,而不是自定义结构
    项42:使用属性来简化反射机制
    项43:不要过分使用反射机制
    项44:创建完整的应用程序专用的异常类

    第6章 其他

    项45:尽量使用强异常保证
    项46:尽量少地使用互操作方法(Interop)
    项47:尽量使用安全代码
    项48:关注开发工具和资源
    项49:为C#2.0做好准备
    项50:关注ECMA标准

    展开全文
  • 最简单的IL程序 .assembly test {} .method void Func() { .entrypoint ldstr "hello world" call void [mscorlib]System.Console::WriteLine(string) ret } 对上面的程序说明如下: ....assemble伪指令用来声明...

    最简单的IL程序

    .assembly test {}
    .method void Func()
    {
        .entrypoint
        ldstr "hello world"
        call void [mscorlib]System.Console::WriteLine(string)
        ret
    }

    对上面的程序说明如下:

    • .assemble伪指令用来声明程序集,该关键字是必须的
    • .method伪指令用来申明方法
    • .entrypoint伪指令用来表示程序的入口函数(方法),一个程序只能有一个入口,且不能放在实例方法中
    • ldstr指令是 load a string on stock 的缩写,表示把一个字符串入栈
    • call指令用来调用方法,参数取值栈顶。[mscorlib]表示调用方法所在程序集,类名和方法名之间用::隔开。
    • ret指令表示方法返回,应该是 return 的缩写

    打开VS20XX开发人员命令提示工具,输入如下命令可编译IL程序为可执行文件:

    ilasm test.il

    函数和方法

    上面的例子中,入口“方法”Func不属于任何一个类,为了区别于实例方法和静态方法,下文中称之为“函数”,IL中既可以写方法也可以写函数,而且函数可以作为程序的入口点,有点类似C++。声明一个方法的语法如下:

    .method [public|private|family|assembly|famorassem|famandassem|privatescope] [hidebysig] [static|instance] 返回值类型 方法名(参数类型, 参数类型2...)[il managed]
    {
        //方法体
        ret
    }

    访问限制修饰符

    • public 等同于C#的public
    • private 等同于C#的private
    • family 等同于C#的protected
    • assembly 等同于C#的internal
    • famorassem fam是family的缩写,assem是assembly的缩写,等同于C#的protected internal
    • famandassem C#中没有对应的修饰符
    • privatescope 当前的module(一个程序集中可以包含多个module)中随处可访问

    其他常见修饰符

    • hidebysig 相当于C#方法前面的new修饰符
    • static和instance 前者表示静态方法,后者表示实例方法

    方法的调用

    请看实例:

    namespace ILTest
    {
        public sealed class Program
        {
            public static void Main(string[] args)
            {
                int result = Program.Add(1, 2);
            }
    
            public static int Add(int a, int b)
            {
                return a + b;
            }
        }
    }

    IL:

    .method public hidebysig static void Main(string[] args) cil managed 
    {
        .maxstack 2
        .entrypoint
        .locals init (
            [0] int32 result
        )
    
        IL_0001: ldc.i4.1 //将第1参数入栈
        IL_0002: ldc.i4.2 //将第2参数入栈
        IL_0003: call int32 ILTest.Program::Add(int32, int32) //调用方法Add,参数pop自栈顶
        IL_0008: stloc.0 //Add方法内已经将计算结果放到了栈顶,此处将栈顶数据赋值变量result
        IL_0009: ret //方法结束
    } 
    
    .method public hidebysig static int32 Add(int32 a, int32 b) cil managed 
    {
        .maxstack 2
        .locals init (
            [0] int32 CS$1$0000
        )
    
        IL_0001: ldarg.0 //将第一个参数入栈
        IL_0002: ldarg.1 //将第二个参数入栈
        IL_0003: add //从栈中pop两个数,执行加法计算后将结果入栈
        IL_0004: stloc.0 //将栈顶数据pop并赋值给变量CS$1$0000
        IL_0005: br.s IL_0007 //跳转到行IL_0007
    
        IL_0007: ldloc.0 //将变量CS$1$0000入栈
        IL_0008: ret //方法结束,将返回值推送到调用者栈
    }

    上例可见,返回值在子方法中被入栈,父方法中再从栈顶出栈,方法的返回值通过栈来实现传递。

    命名空间和类

    下面是一个最简单的具有命名空间和类的例子:

    .assembly test {}
    .namespace test.com.joey
    {
        .class Program
        {
            .method static void Main()
            {
                .entrypoint
                ldstr "hello world"
                call void [mscorlib]System.Console::WriteLine(string)
                ret
            }
        }
    }

    类的常见修饰符有如下这些:

    • public|private 相当于C#的public和Internal
    • abstract 表示抽象类
    • sealed 表示封闭类
    • ansi 类中字符串编码格式,可选项还有unicodeautochar(根据不同的平台,会自动转换成相对应的字符集)
    • auto 告诉运行时(CLR)自动为非托管内存中的对象的成员选择适当的布局,可选项还有sequentialexplicit

    字段和构造函数

    编写如下C#代码:

    namespace ILTest
    {
        public class Program
        {
            private int _var = 100;
            private static int _staticVar = 100;
            public static void Main(string[] args)
            {
            }
        }
    }

    编译为IL:
    捕获.PNG-38.5kB
    请看第5和第6行代码,.field伪指令用来声明字段,虽然C#代码中为这个两个字段赋了默认值,但是IL代码中并没有,真正的赋值操作是在默认构造函数和静态构造函数完成的。

    请看从行号23开始的默认构造函数(.ctor),ldc.i4.s 100表示将100入栈(凡是ld开头的指令多是入栈指令),stfld int32 ILTest.Program::_var表示将栈顶数据赋值给字段_var(凡是st打头的指令多是赋值指令)。再看从39行开始的静态构造函数(.cctor),静态字段声明是赋值其实也是在静态构造函数里完成的。

    在做一个有趣的实验,将上面的C#代码中添加构造函数如下:

    public Program()
    {
        _var = 200;
    }

    再看生产的IL代码中的构造函数:
    无标题.png-16.7kB

    _var变量居然被赋值了2次,2次!可见,C#编译器并未就这种情况作出优化,不过貌似没人会写这么傻瓜的代码吧,声明时赋值后又在无参构造函数中赋值。大家有兴趣可以试试静态变量,情况也是一样一样的。

    还有一点需要注意,字段声明时赋值总是放在构造函数的最前面,然后是调用父类构造函数(第20行),最后才是自己写的代码,而静态构造函数的又在非静态构造函数之前执行,所有,实例化一个类时,正确的执行顺序就是这样的:

    1. 静态字段赋值(如果声明的同时就赋值的话)
    2. 静态构造函数
    3. 非静态字段赋值(如果声明的同时就赋值的话)
    4. 非静态父类构造函数
    5. 非静态子类构造函数

    学了IL后妈妈再也不用担心我记不住类的实例化执行顺序了。

    另外需要注意的地方是,如果C#类中没有无参构造函数,那么C#编译器会自动生成,但是静态构造函数就不会制动时生成了。

    局部变量

    编写C#代码如下:

    namespace ILTest
    {
        public class Program
        {
            public static void Main(string[] args)
            {
                int intVar = 100;
                float floatVar = 101f;
                String stringVar = "hello";
    
                Console.WriteLine(intVar);
                Console.WriteLine(floatVar);
                Console.WriteLine(stringVar);
            }
        }
    }

    编译为IL:
    无标题.png-24.9kB

    由上图可见,局部变量相关的步骤可分为3步:
    第一步:编号
    .locals init伪指令负责把局部变量从0开始编号(第14行),后面的代码中只使用这个编号,变量名称不再使用
    第二步:赋值
    ldc.i4.s 100(第21行)将100入栈,接下来stloc.0表示把栈顶值赋值给第0个变量
    第三步:使用
    ldloc.0指令表示把第0个变量入栈(第27行),接下来System.Console::WriteLine方法从栈顶得到该变量的值

    条件判断与循环

    IL没有提供ifwhile等循环,只有br跳转指令或brXXX等有条件跳转指令,C#编译器或将C#的条件判断和循环编译为br跳转指令,请看如下的例子:

    public static void Main(string[] args)
    {
        bool symbol = false;
        if (symbol)
        {
            Console.WriteLine("hello");
        }
    }

    IL:

    .method public hidebysig static void Main (string[] args) cil managed 
    {
        .maxstack 2
        .entrypoint
        .locals init (
            [0] bool symbol, //C#代码声明的变量
            [1] bool CS$4$0000 //编译器自动生成一个变量
        )
    
        IL_0001: ldc.i4.0 //把0入栈,0用来表示false
        IL_0002: stloc.0 //把0出栈并赋值给变量symbol
        IL_0003: ldloc.0 //把变量symbol的值0入栈
        IL_0004: ldc.i4.0 //把0入栈,0用来表示false
        IL_0005: ceq //对栈顶和栈中第二个数出栈并比较其是否相等,如果相等将1入栈,否则将0入栈
        IL_0007: stloc.1 //将栈顶元素出栈并赋值给变量CS$4$0000,该变量存储指令ceq执行的结果
        IL_0008: ldloc.1 //将变量CS$4$0000的值入栈,该变量存储指令ceq执行的结果
        IL_0009: brtrue.s IL_0018 //如果栈顶元素是1,那么跳转到IL_0018行
    
        IL_000c: ldstr "hello"
        IL_0011: call void [mscorlib]System.Console::WriteLine(string)
    
        IL_0018: ret
    } 

    循环语句亦是如此,不在赘述。

    常用指令备忘

    上面所说的是IL中最为基础的部分,如果要想再深入学习,只需编写C#代码并编译为IL查看即可,有了上面的基础应该可以看懂了。下面列举一些常用的IL指令以供不时之查:

    指令 说明
    Add
    Sub
    Mul
    Div
    Rem 取余
    Xor 按位异或
    And 按位与
    Or 按位或
    Not 按位补
    Dup 复制计栈顶端值,然后将副本入栈
    Neg 按位反
    Ret 从当前方法返回,并将返回值(如果存在)从子方法栈推送到调用方法的栈上
    Jmp 退出当前方法并跳至指定方法
    Newobj 创建对象新实例,并将对象引用推送到栈上
    Newarr 创建数组,并将数组引用推送到栈上
    Nop Debug模式下生成,断点设置辅助
    Initobj 将位于指定地址的值类型的每个字段初始化为空引用或适当的基元类型的 0
    Isinst 测试对象引用是否为特定类的实例
    Sizeof
    Box 装箱
    Unbox 拆箱
    Castclass 类型转换
    Switch 实现跳转表
    Throw 引发异常
    Call 调用静态方法
    Callvirt 调用实例方法或虚方法

    参考资料

    (翻译) 《C# to IL》
    Introduction to IL Assembly Language
    IL汇编语言介绍(译)
    30分钟?不需要,轻松读懂IL

    转载于:https://www.cnblogs.com/zzy0471/p/5943332.html

    展开全文
  • Effective C# 第一章 C#语言元素 项1:总是使用属性,不要使用可访问的数据成员项2:常数项尽量使用readonly,而不是const项3:类型装换时,不要使用强制转换,使用操作符is或者as项4:使用Conditional标记代替#...
  • IL是微软推出的一种面向对象的类似汇编指令集合的中间语言,无论是C#还是VB代码,经过不同的编译器可编译为无差别的IL,或者说单看IL代码是无法分辨出它是来自C#还是VB,IL类似于Java的.Class文件,...
  • C#精读研习摘要

    2017-06-05 13:50:00
    2019独角兽企业重金招聘Python工程师标准>>> ...
  • C# winform上位机 摘要

    千次阅读 2016-09-30 13:39:29
    双核 叫 物理双核 硬件线程 又叫 逻辑内核 传统的代码都是串行,为了实现加速而开了很多工作线程,这些工作线程就是软件线程。 ...System.Threading.Tasks ...****************************************************...
  • C# 读写文件摘要

    2018-11-20 16:33:00
    首先下载微软提供的工具:DsoFile (微软官网下载...读写自定义摘要信息(需要注意,自定义摘要信息只能添加一次,再添加会报错,所以如果对应的name已经存在,只能采用修改的方式添加) /// <summary> ...
  • C#修改文件属性摘要信息

    热门讨论 2012-07-02 14:08:56
    C#修改文件属性摘要信息 1.添加依赖库:ole32.dll 2.调用静态方法:FileSummary.SetProperty(文件全路径名,修改内, 属性类型);即可。
  • private void GetCount(TextBOX txt_str,TextBOXtxt_count) { int P_scalar = 0;//定义值类型变量并赋值为0 Regex P_regex = //创建正则表达式对象,用于判断字符是否为汉字 new Regex("^[\u4E00-...
  • C#学习摘要之(一)

    2006-03-09 01:34:00
    一、C#的特点1) 语法简洁 C#不允许直接内存操作;C#没有指针;C#的关键字更加明了.2) 面向对象设计 C#中的每种类型都可以当作是对象;C#只允许单继承,也没有全局变量和全局常数,所有的一切都必须封装在一个类中,使...
  • mapxtreme+c#实战摘要(一)

    千次阅读 2005-11-23 17:02:00
    ppp80近日用了一下mapxtreme for .net。虽然感觉没有mapx的好用,不过这个可以和.net结合,已经很满足了。不过我的程序只用了一点点mapxtreme的东西,所以发掘的东西很少,先记在下边:1创建临时层MapInfo.Data....
  • C#信息摘要算法(MD5)

    千次阅读 2014-12-23 10:27:21
    MD5 是 Message Digest Algorithm 5(信息摘要算法)的缩写,MD5 一种散列(Hash)技术,广泛用于加密、解密、数据签名和数据完整性校验等方面。任何一个文件,无论是可执行程序、图像文件、临时文件或者其他任何类型...
  • Excel、Exchange 和 C#Eric GunnersonMicrosoft Corporation 2003年4月21日摘要:Eric Gunnerson 将向您介绍如何使用 Outlook、Excel 和 C# 创建自定义的日历,该日历可以提供适用于短期项目和长期项目的清晰明了的...
  • C# 串口通讯摘要(转)

    千次阅读 2016-12-05 23:21:45
    串口通讯摘要(转) 串口通信之并发与单步 物理连接示意图如下所示,每个串口挂接多个采集器。 通信协议: 包头(1B) + 地址码(1B) + 命令字(1B) + 数据长度(1B) + 校验码1(1B) + 数据...
  • 参考:... 1. 用VS建立一个 Windows Service 类型(中文版为Windows服务)的项目,建立完成后的项目目录类似于: 2.切换到Services1.cs的设计界面, 并打开其属性选项卡: ...
  • c#中读取文件摘要信息

    千次阅读 2011-06-30 11:36:00
    首先下载微软提供的DsoFile组件 : DsoFile读写代码:using System;using DSOFile;public partial class _Default : System.Web.UI.Page{protected void Page_Load(object sender, EventArgs e){string path = “F:图...
  • MD5即Message-Digest Algorithm 5(信息-摘要算法5),用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一(又译摘要算法、哈希算法) MD5算法具有以下特点: 1、压缩性:任意长度的数据,算出的MD5值长度...

空空如也

1 2 3 4 5 ... 20
收藏数 4,275
精华内容 1,710
关键字:

c# 摘要

c# 订阅