cref - summary example c#
IL Instrucciones no expuestas por C# (4)
Me refiero a instrucciones como sizeof y cpblk; no existe una clase o comando que ejecute estas instrucciones (sizeof en C # se calcula en tiempo de compilación, no en tiempo de ejecución AFAIK).
Esto es incorrecto. sizeof(int)
se tratará como la constante de tiempo de compilación 4, por supuesto, pero hay muchas situaciones (todas en código unsafe
) donde el compilador se basa en el tiempo de ejecución para determinar cuál es el tamaño de la memoria de una estructura. Considere, por ejemplo, una estructura que contiene dos punteros. Sería del tamaño 8 en una máquina de 32 bits pero 16 en una máquina de 64 bits. En esas circunstancias, el compilador generará el tamaño del código de operación.
¿Otros?
No tengo una lista de todos los códigos de operación que no producimos. Nunca tuve la necesidad de crear una lista de este tipo. Sin embargo, fuera de mi cabeza puedo decirte que no hay forma de generar una instrucción de "llamada indirecta" (calli) en C #; de vez en cuando nos preguntan por esa característica, ya que mejoraría el rendimiento de ciertos escenarios de interoperabilidad.
ACTUALIZACIÓN: Acabo de descifrar el código fuente para producir una lista de códigos de operación que definitivamente producimos. Son:
añadir
add_ovf
add_ovf_un
y
arglist
beq
beq_s
bge
bge_s
bge_un
bge_un_s
bgt
bgt_s
bgt_un
bgt_un_s
ble
ble_s
ble_un
ble_un_s
blt
blt_s
blt_un
blt_un_s
bne_un
bne_un_s
caja
br
br_s
alegre
brfalse_s
brtrue
brtrue_s
llamada
callvirt
castclass
ceq
cgt
cgt_un
clt
clt_un
constreñido
conv_i
conv_ovf_i
conv_ovf_i_un
conv_ovf_u
conv_ovf_u_un
conv_r
conv_r_un
conv_u
div
div_un
dup
endfinally
initobj
isinst
ldarg
ldarg_
ldarg_s
ldarga
ldarga_s
ldc_i
ldc_r
ldelem
ldelem_i
ldelem_r
ldelem_ref
ldelem_u
ldelema
ldfld
ldflda
ldftn
ldind_i
ldind_r
ldind_ref
ldind_u
ldlen
ldloc
ldloc_
ldloc_s
ldloca
ldloca_s
ldnull
ldobj
ldsfld
ldsflda
ldstr
ldtoken
ldvirtftn
salir
hojas
localloc
mkrefany
mul
mul_ovf
mul_ovf_un
neg
Newarr
newobj
nop
no
o
popular
solo lectura
refanytype
refanyval
movimiento rápido del ojo
rem_un
retirado
volver a tirar
Shl
shr
shr_un
tamaño de
starg
starg_s
stelem
stelem_i
stelem_r
stelem_ref
stfld
stind_i
stind_r
stind_ref
stloc
stloc_s
stobj
stsfld
sub
sub_ovf
sub_ovf_un
cambiar
lanzar
unbox_any
volátil
xor
No voy a garantizar que sean todos ellos, pero ciertamente es la mayoría de ellos. Luego puede comparar eso con una lista de todos los códigos de operación y ver qué falta.
¿Qué instrucciones de IL no están expuestas por C #?
Me refiero a instrucciones como sizeof y cpblk; no existe una clase o comando que ejecute estas instrucciones (sizeof en C # se calcula en tiempo de compilación, no en tiempo de ejecución AFAIK).
¿Otros?
EDITAR: El motivo por el que estoy preguntando esto (y afortunadamente esto hará que mi pregunta sea un poco más válida) es porque estoy trabajando en una pequeña biblioteca que proporcionará la funcionalidad de estas instrucciones. sizeof y cpblk ya están implementados. Quería saber qué otros podría haber perdido antes de continuar.
EDIT2: Utilizando la respuesta de Eric, he compilado una lista de instrucciones:
- Descanso
- Jmp
- Calli
- Cpobj
- Ckfinite
- Prefijo [1-7]
- Prefixref
- Filtro final
- Desalineado
- Tailcall
- Cpblk
- Initblk
Hubo varias otras instrucciones que no fueron incluidas en la lista, que estoy separando porque básicamente son accesos directos para otras instrucciones (comprimidas para ahorrar tiempo y espacio):
- Ldarg [0-3]
- Ldloc [0-3]
- Stloc [0-3]
- Ldc_ [I4_ [M1 / S / 0-8] / I8 / R4 / R8]
- Ldind_ [I1 / U1 / I2 / U2 / I4 / U4 / I8 / R4 / R8]
- Stind_ [I1 / I2 / I4 / I8 / R4 / R8]
- Conv_ [I1 / I2 / I4 / I8 / R4 / R8 / U4 / U8 / U2 / U1]
- Conv_Ovf_ [I1 / I2 / I4 / I8 / U1 / U2 / U4 / U8]
- Conv_Ovf_ [I1 / I2 / I4 / I8 / U1 / U2 / U4 / U8] _Un
- Ldelem_ [I1 / I2 / I4 / I8 / U1 / U2 / U4 / R4 / R8]
- Stelem_ [I1 / I2 / I4 / I8 / R4 / R8]
En base a la respuesta de Eric aquí hay algunos que he visto. Donde puedo ver una razón por la que lo indiqué, si no lo hago, especulo libremente. Siéntase libre de indicar si esas especulaciones son incorrectas.
Break
Señala la Common Language Infrastructure (CLI) para informar al depurador que se ha desconectado un punto de interrupción.
Usted haría esto llamando a System.Diagnostics.Debugger.Break (), esto parece no utilizar esa instrucción directamente, sino que utiliza un método BreakInternal () cocido en el CLR.
Copia un número especificado de bytes desde una dirección de origen a una dirección de destino. Copia el tipo de valor ubicado en la dirección de un objeto (tipo &, * o int nativo) a la dirección del objeto de destino (tipo &, * o int nativo).
Supongo que estos fueron agregados para C ++ / CLI (previamente administrado C ++), pero eso es pura especulación por mi parte. También pueden estar presentes en ciertas llamadas al sistema pero no generadas normalmente por el compilador y proporcionar cierto margen para la diversión y los juegos no seguros.
Transfiere el control de la cláusula de filtro de una excepción al manejador de excepciones Common Language Infrastructure (CLI).
C # no admite el filtrado de excepciones. Sin embargo, el compilador de VB hace uso de esto.
Inicializa un bloque de memoria especificado en una dirección específica para un tamaño y valor inicial determinados.
Voy a especular de nuevo que esto es potencialmente útil en códigos inseguros y C ++ / CLI
Sale del método actual y salta al método especificado.
Voy a especular que este tipo de trampolín puede ser útil para aquellos que desean evitar las llamadas finales. Tal vez el DLR hace uso de ella?
Realiza una instrucción de llamada de método postfixed de modo que el marco de pila del método actual se elimine antes de que se ejecute la instrucción de llamada real.
Discutido en profundidad en otra parte, actualmente el compilador de c # no emite este código de operación
Indica que una dirección actualmente encima de la pila de evaluación puede no estar alineada con el tamaño natural de las siguientes instrucciones ldind, stind, ldfld, stfld, ldobj, stobj, initblk o cpblk.
C # (y el CLR) ofrece bastantes garantías sobre la naturaleza alineada de gran parte de su código y datos resultantes. No es sorprendente que esto no se emita, pero puedo ver por qué se incluiría.
Convierte la representación en recuadro de un tipo de valor en su forma no agrupada.
El compilador de c # prefiere usar la instrucción Unbox exclusivamente para este propósito. Supongo que, basado en la adición de esto al conjunto de instrucciones en la versión 2.0, hace que los genéricos sean factibles o mucho más simples. En ese punto, usarlo en todo el código para todo, genéricos u otros, era más seguro, más simple o más rápido (o una combinación de todos).
Nota:
Prefix1 , Prefijo2, Prefijo3, Prefijo4, Prefijo5, Prefijo6, Prefijo7, Prefijoref
Infraestructura. Esta es una instrucción reservada.
Estas no son instrucciones como tales, algunas instrucciones de IL son más largas que otras. Estas de longitud variable deberían comenzar con prefijos que nunca son válidos por sí mismos para hacer que el análisis sea claro. Estos prefijos de prefijo están reservados para eso, por lo que no se usan en ningún otro lugar. Sin duda, alguien que implementa un analizador sintáctico basado en la secuencia de conmutación para una secuencia IL apreciaría estos para poder atraparlos y mantener el estado.
La directiva .override
IL (no sé si es el término correcto, pero ciertamente no es una instrucción ) la genera el compilador C #, pero solo en el caso especial de la implementación explícita de la interfaz.
Sería interesante poder usarlo más libremente, como en VB.NET, donde los miembros implementadores pueden tener un alias o incluso tener un modificador de acceso diferente que el miembro de la interfaz.
Un ejemplo interesante es tail.call
( Tailcall ) que haría posible la Optimización de llamadas en cola para la recursión.