Share via

OpCodes.Callvirt Field


Calls a late-bound method on an object, pushing the return value onto the evaluation stack.

public: static initonly System::Reflection::Emit::OpCode Callvirt;
public static readonly System.Reflection.Emit.OpCode Callvirt;
 staticval mutable Callvirt : System.Reflection.Emit.OpCode
Public Shared ReadOnly Callvirt As OpCode 

Field Value


The following table lists the instruction's hexadecimal and Microsoft Intermediate Language (MSIL) assembly format, along with a brief reference summary:

Format Assembly Format Description
6F < T > callvirt method Calls a specific method associated with obj.

The stack transitional behavior, in sequential order, is:

  1. An object reference obj is pushed onto the stack.

  2. Method arguments arg1 through argN are pushed onto the stack.

  3. Method arguments arg1 through argN and the object reference obj are popped from the stack; the method call is performed with these arguments and control is transferred to the method in obj referred to by the method metadata token. When complete, a return value is generated by the callee method and sent to the caller.

  4. The return value is pushed onto the stack.

The callvirt instruction calls a late-bound method on an object. That is, the method is chosen based on the runtime type of obj rather than the compile-time class visible in the method pointer. Callvirt can be used to call both virtual and instance methods. The callvirt instruction may be immediately preceded by a tail (Tailcall) prefix to specify that the current stack frame should be released before transferring control. If the call would transfer control to a method of higher trust than the original method the stack frame will not be released.

The method metadata token provides the name, class and signature of the method to call. The class associated with obj is the class of which it is an instance. If the class defines a non-static method that matches the indicated method name and signature, this method is called. Otherwise all classes in the base class chain of this class are checked in order. It is an error if no method is found.

Callvirt pops the object and the associated arguments off the evaluation stack before calling the method. If the method has a return value, it is pushed on the stack upon method completion. On the callee side, the obj parameter is accessed as argument 0, arg1 as argument 1, and so on.

The arguments are placed on the stack in left-to-right order. That is, the first argument is computed and placed on the stack, then the second argument, then the third, until all necessary arguments are atop the stack in descending order. The instance reference obj (always required for callvirt) must be pushed before any of the user-visible arguments. The signature (carried in the metadata token) need not contain an entry in the parameter list for the this pointer.

Note that a virtual method can also be called using the Call instruction.

MissingMethodException is thrown if a non-static method with the indicated name and signature could not be found in the class associated with obj or any of its base classes. This is typically detected when Microsoft Intermediate Language (MSIL) instructions are converted to native code, rather than at runtime.

NullReferenceException is thrown if obj is null.

SecurityException is thrown if system security does not grant the caller access to the called method. The security check may occur when the CIL is converted to native code rather than at run time.


When calling methods of System.Object on value types, consider using the constrained prefix with the callvirt instruction. This removes the need to emit different IL depending on whether or not the value type overrides the method, avoiding a potential versioning problem. Consider using the constrained prefix when invoking interface methods on value types, since the value type method implementing the interface method can be changed using a MethodImpl. These issues are described in more detail in the Constrained opcode.

The following Emit method overload can use the callvirt opcode:

Applies to