能否直接在Null实例上调用方法?
摘要:前几天有个网友问我一个问题:调用实例方法的时候为什么目标对象不能为Null。看似一个简单的问题,还真不是一句话就能说清楚的。而且这个结论也不对,当我们调用定义在某个类型的实例方法时,目标对象其实可以为Null。一、从ECMA-335 Spe
前几天有个网友问我一个问题:调用实例方法的时候为什么目标对象不能为Null。看似一个简单的问题,还真不是一句话就能说清楚的。而且这个结论也不对,当我们调用定义在某个类型的实例方法时,目标对象其实可以为Null。
一、从ECMA-335 Spec说起
二、Call V.S Callvirt
三、直接调用(C#)
四、静态方法
五、值类型实例方法
六、?.操作符
七、扩展方法
一、从ECMA-335 Spec说起A method that is associated with an instance of the type is either an instance method or a virtual
method (see §I.8.4.4). When they are invoked, instance and virtual methods are passed the
instance on which this invocation is to operate (known as this or a this pointer).
The fundamental difference between an instance method and a virtual method is in how the
implementation is located. An instance method is invoked by specifying a class and the instance
method within that class. Except in the case of instance methods of generic types, the object
passed as this can be null (a special value indicating that no instance is being specified) or an
instance of any type that inherits (see §I.8.9.8) from the class that defines the method. A virtual
method can also be called in this manner. This occurs, for example, when an implementation of a
virtual method wishes to call the implementation supplied by its base class. The CTS allows this
to be null inside the body of a virtual method.
A virtual or instance method can also be called by a different mechanism, a virtual call. Any
type that inherits from a type that defines a virtual method can provide its own implementation of
that method (this is known as overriding, see §I.8.10.4). It is the exact type of the object
(determined at runtime) that is used to decide which of the implementations to invoke.
上面这段文字节选自Common Language Infrastructure (CLI),我来简单总结一下:
与某个类型实例关联的方法,也就是被我们统称为实例方法,其实进一步划分为Instance Method和Virtual Method。我觉得将它们称为非虚实例方法(Non-Virtual Instance Method)和虚实例方法(Virtual Instance Method)更清楚;从IL指令来看,方法有Call和Callvirt两种调用方式。两种实例方法类型+两种调用方式,所以一共就有四种调用场景;Call指令直接调用声明类型的方法,实在编译时决定的;Callvirt指令调用的是目标对象真实类型的方法,只能在运行时确定。
