OpCodes.Readonly Campo

Definição

Especifica que a operação subsequente de endereçamento do array não realiza verificação de tipo em tempo de execução, e que devolve um ponteiro gerido cuja mutabilidade é restringida.

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

Valor de Campo

Observações

A tabela seguinte lista o formato hexadecimal e assembly da linguagem intermédia Microsoft (MSIL) da instrução, juntamente com um breve resumo de referência:

Formato Formato de Montagem Description
FE 1E Apenas leitura. Especifique que a operação subsequente de endereçamento do array não realiza verificação de tipo em tempo de execução e que devolve um ponteiro gerido com mutabilidade restrita.

Este prefixo só pode aparecer imediatamente antes da ldelema instrução e chamadas ao método especial Address em arrays. O seu efeito na operação subsequente é duplo:

  1. Em tempo de execução, não é realizada nenhuma operação de verificação de tipo. Note que normalmente existe uma verificação implícita de tipos para as ldelema instruções e stelem quando usadas em arrays de tipos de referência. Nunca existe uma verificação de tipo em tempo de execução para classes de valor, por isso readonly existe um no-op nesse caso.

  2. O verificador trata o resultado da operação address-of como um ponteiro gerido com mutabilidade restrita.

Diz-se que o ponteiro tem mutabilidade restrita porque o tipo definidor controla se o valor pode ser mutado. Para classes de valor que não expõem campos públicos ou métodos que atualizem o valor no local, o ponteiro é apenas de leitura (daí o nome do prefixo). Em particular, as classes que representam tipos primitivos (por exemplo, System.Int32) não expõem mutadores e, por isso, são apenas de leitura.

Um ponteiro gerido restrito desta forma só pode ser usado das seguintes formas:

  • Como object parâmetro para as ldfldinstruções, ldflda, , stfldcall, , ouconstrained callvirt instruções.

  • Como pointer parâmetro para a ldobj instrução ou para uma das ldind instruções.

  • Como source parâmetro da cpobj instrução.

Todas as outras operações são proibidas, incluindo as stobj, , ou mkrefany operações, ou qualquer uma das stind instruçõesinitobj.

O objetivo do readonly prefixo é evitar uma verificação de tipo ao obter um elemento de um array em código genérico. Por exemplo, a expressão arr[i].m(), onde o tipo de elemento do array arr é um tipo genérico que foi restringido a ter uma interface com o método m, pode compilar para o MSIL seguinte.

ldloc arr
ldloc i
readonly.
ldelema !0    // Loads the pointer to the object.
…             // Load the arguments to the call.
constrained. !0
callvirt m

Sem o readonly prefixo, a ldelema instrução realizaria uma verificação de tipo no caso em que !0 fosse um tipo de referência. Este tipo de verificação não só é ineficiente, como também é semanticamente incorreto. O teste de tipo para ldelema é uma correspondência exata, o que é demasiado forte. Se o array contivesse subclasses de tipo !0, o código acima falharia a verificação de tipo.

O endereço do elemento do array é obtido, em vez do próprio elemento, para ter um handle para arr[i] que funcione tanto para tipos de valor como para tipos de referência, podendo assim ser passado para a constrained callvirt instrução.

Em geral, seria inseguro saltar a verificação de tempo de execução se o array contivesse elementos de um tipo de referência. Para garantir, é necessário garantir que nenhuma modificação ao array seja feita através deste ponteiro. As regras do verificador garantem isso. O ponteiro gerido restrito pode ser passado como objeto das chamadas de método de instância, pelo que não é estritamente de leitura para tipos de valor, mas não existe problema de segurança de tipos para tipos de valor.

O seguinte Emit método de sobrecarga pode usar o readonly opcode:

Aplica-se a