zoukankan      html  css  js  c++  java
  • clr via c#读书笔记四:call、callvirt

    1、嵌套类,就是定义在类中的类;嵌套类可以访问外部类的方法、属性、字段而不管访问修饰符的限制,但是外部类只能够访问修饰符为public、internal的嵌套类的字段、方法、属性;

    2、CLR如何调用虚方法、属性和事件:

    IL提供两个方法调用指令:call和callvirt。

    call调用静态方法、实例方法和虚方法;callvirt调用实例方法和虚方法,不能调用静态方法;

    call关心的是编译时类型;callvirt关心的是运行时类型;所以,用callvirt调用虚方法时,CLR要调查发生调用的对象的实际类型,为了确定类型,发生调用的变量绝不能是null。

    如有两个类:

    internal class Person{
        
    }
    internal class Employee:Person{
    
    }
    void main(){
       Person p=new Employee();//p在编译时的类型是Person,而在运行时的类型是Employee
    }
    

    call不会检测对象是否为null。而callvirt会检测。所以callvirt指令的执行速度比call指令稍慢。

    3、C#用callvirt指令调用所有实例方法。

    但是编辑器有时用call而不是callvirt调用虚方法。虽然刚开始有点难以理解,但是以下证明了有时需要这样做:

    internal class SomeClass{
        //ToString是基类Object定义的虚方法
        public override String ToString(){
            //编译器使用IL指令'call'
            //以非虚方式调用Object的ToString方法
            //如果编辑器用'callvirt'而不是'call',
            //那么该方法将递归调用自身,直至栈溢出(但是为什么会递归调用自身呢,这里不是base吗,是基类吗?)
            return base.ToString();
        //我的理解:这里实际和reutrn this.ToString()没区别,因为base虽然是基类指针,但是用callvirt时,会检测实际类型,而实际类型就是自身,所有会无限递归调用自身的方法。(不知识这样理解对不对)
      }
    }
    

      

  • 相关阅读:
    spring学习记录_Spring中的新注解
    spring学习记录_spring的 注解
    spring学习记录_spring的 ioc核心容器
    关于myeclipse项目运行报错:Access denied for user 'root'@'localhost' (using password: YES)
    vue项目中实现多语言切换
    OC中限制UITextView的最大字数的实现
    简单瀑布流的实现
    仿购物车的实现
    仿QQ好友列表界面的实现
    类似QQ侧滑菜单功能实现
  • 原文地址:https://www.cnblogs.com/yuzhoumanwu/p/8537464.html
Copyright © 2011-2022 走看看