Todo el código escrito en lenguajes .NET se compila en MSIL, pero ¿hay tareas / operaciones específicas que solo puede hacer usando MSIL directamente?
Hagamos también que las cosas se hagan más fácilmente en MSIL que C #, VB.NET, F #, j # o cualquier otro lenguaje .NET.
Hasta ahora tenemos esto:
- Recursividad de la cola
- Co / Contravarianza Genérica
- Sobrecargas que difieren solo en los tipos de retorno
- Anular modificadores de acceso
- Tener una clase que no pueda heredar de System.Object
- Excepciones filtradas (se puede hacer en vb.net)
- Llamando a un método virtual del tipo de clase estática actual.
- Obtenga un identificador de la versión en caja de un tipo de valor.
- Haz un intento / falla.
- Uso de nombres prohibidos.
- Defina sus propios constructores sin parámetros para los tipos de valor .
- Definir eventos con un
raise
elemento. - Algunas conversiones permitidas por el CLR pero no por C #.
- Hacer un
main()
método no como el.entrypoint
. - trabajar con los tipos nativos
int
y nativosunsigned int
directamente. - Juega con punteros transitorios.
- directiva emitbyte en MethodBodyItem
- Lanza y atrapa tipos que no sean del sistema.
- Heredar enumeraciones (sin verificar)
- Puede tratar una matriz de bytes como una matriz (4x más pequeña) de entradas.
- Puede tener un campo / método / propiedad / evento, todos tienen el mismo nombre (sin verificar).
- Puede volver a ramificarse en un bloque try desde su propio bloque catch.
- Tiene acceso al especificador de acceso famandassem (
protected internal
es fam o assem) - Acceso directo a la
<Module>
clase para definir funciones globales, o un inicializador de módulo.
Respuestas:
MSIL permite sobrecargas que difieren solo en los tipos de retorno debido a
o
fuente
La mayoría de los lenguajes .Net, incluidos C # y VB, no utilizan la función de recursión de cola del código MSIL.
La recursividad de cola es una optimización que es común en lenguajes funcionales. Ocurre cuando un método A termina devolviendo el valor del método B de tal manera que la pila del método A se puede desasignar una vez que se realiza la llamada al método B.
El código MSIL admite la recursión de cola explícitamente, y para algunos algoritmos podría ser una optimización importante. Pero dado que C # y VB no generan las instrucciones para hacerlo, debe hacerse manualmente (o usando F # o algún otro lenguaje).
Aquí hay un ejemplo de cómo la recursividad de cola puede implementarse manualmente en C #:
Es una práctica común eliminar la recursividad moviendo los datos locales de la pila de hardware a una estructura de datos de pila asignada en el montón. En la eliminación de recursión de cola como se muestra arriba, la pila se elimina por completo, lo cual es una optimización bastante buena. Además, el valor de retorno no tiene que recorrer una larga cadena de llamadas, sino que se devuelve directamente.
Pero, de todos modos, el CIL proporciona esta característica como parte del lenguaje, pero con C # o VB debe implementarse manualmente. (El jitter también es libre de hacer esta optimización por sí solo, pero ese es un problema completamente diferente).
fuente
En MSIL, puede tener una clase que no puede heredar de System.Object.
Código de muestra: compílelo con ilasm.exe ACTUALIZACIÓN: debe usar "/ NOAUTOINHERIT" para evitar que el ensamblador se herede automáticamente.
fuente
TypeLoadException
). PEVerify devuelve: [MD]: Error: TypeDef que no es una interfaz y que la clase Object no extiende el token Nil.Es posible combinar los modificadores
protected
yinternal
acceder. En C #, si escribeprotected internal
, se puede acceder a un miembro desde el ensamblado y desde las clases derivadas. A través de MSIL puede obtener un elemento que se puede acceder desde las clases derivadas dentro del conjunto única . (¡Creo que podría ser muy útil!)fuente
private protected
Ooh, no vi esto en ese momento. (Si agrega la etiqueta jon-skeet, es más probable, pero no la reviso con tanta frecuencia).
Parece que ya tienes respuestas bastante buenas. Adicionalmente:
object
C #, a veces funcionará. Vea una pregunta uint [] / int [] SO para ver un ejemplo.Agregaré a esto si pienso en otra cosa ...
fuente
<>a
como un nombre en C # ...El CLR ya admite co / contravarianza genérica, pero C # no obtendrá esta característica hasta 4.0
fuente
En IL puedes lanzar y atrapar cualquier tipo, no solo los tipos derivados
System.Exception
.fuente
try
/catch
sin paréntesis en la declaración catch, también detectará excepciones que no sean de excepción. Lanzar, sin embargo, solo es posible cuando heredas deException
.IL tiene la distinción entre
call
ycallvirt
para llamadas a métodos virtuales. Al usar el primero, puede forzar la llamada a un método virtual del tipo de clase estática actual en lugar de la función virtual en el tipo de clase dinámica.C # no tiene forma de hacer esto:
VB, como IL, puede emitir llamadas no virtuales mediante el uso de la
MyClass.Method()
sintaxis. En lo anterior, esto seríaMyClass.ToString()
.fuente
En un try / catch, puede volver a ingresar el bloque try desde su propio bloque catch. Entonces, puedes hacer esto:
AFAIK no puedes hacer esto en C # o VB
fuente
GOTO
Catch
a suTry
. Ejecute el código de prueba en línea aquí .Con IL y VB.NET puede agregar filtros al detectar excepciones, pero C # v3 no admite esta función.
Este ejemplo de VB.NET está tomado de http://blogs.msdn.com/clrteam/archive/2009/02/05/catch-rethrow-and-filters-why-you-should-care.aspx (tenga
When ShouldCatch(ex) = True
en cuenta Cláusula de captura):fuente
= True
, ¡me está haciendo sangrar los ojos!Hasta donde sé, no hay forma de crear inicializadores de módulo (constructores estáticos para un módulo completo) directamente en C #:
http://blogs.msdn.com/junfeng/archive/2005/11/19/494914.aspx
fuente
Native types
Puede trabajar directamente con los tipos int nativo e int sin signo nativo (en c # solo puede trabajar en un IntPtr que no es lo mismo.
Transient Pointers
Puede jugar con punteros transitorios, que son punteros a tipos administrados pero garantizados para no moverse en la memoria ya que no están en el montón administrado. No estoy completamente seguro de cómo podría usar esto de manera útil sin jugar con el código no administrado, pero no está expuesto a los otros idiomas directamente solo a través de cosas como stackalloc.
<Module>
puede meterse con la clase si así lo desea (puede hacerlo reflexionando sin necesidad de IL)
.emitbyte
.entrypoint
Tiene un poco más de flexibilidad en esto, puede aplicarlo a métodos que no se llaman Main, por ejemplo.
lea las especificaciones , estoy seguro de que encontrará algunas más.
fuente
<Module>
se entiende como una clase especial para lenguajes que aceptan métodos globales (como lo hace VB), pero de hecho, C # no puede acceder a él directamente.Puede hackear la anulación de método co / contra-varianza, que C # no permite (¡esto NO es lo mismo que la varianza genérica!). Tengo más información sobre cómo implementar esto aquí , y las partes 1 y 2
fuente
Creo que lo que seguía deseando (con razones completamente equivocadas) era la herencia en Enums. No parece algo difícil de hacer en SMIL (ya que las enumeraciones son solo clases), pero no es algo que la sintaxis de C # quiera que hagas.
fuente
Aquí hay más:
fuente
20) Puede tratar una matriz de bytes como una matriz (4x más pequeña) de entradas.
Utilicé esto recientemente para hacer una implementación rápida de XOR, ya que la función CLR xor opera en ints y necesitaba hacer XOR en una secuencia de bytes.
El código resultante medido es ~ 10 veces más rápido que el equivalente hecho en C # (haciendo XOR en cada byte).
===
No tengo suficiente stackoverflow street credz para editar la pregunta y agregar esto a la lista como # 20, si alguien más pudiera hacerlo, sería genial ;-)
fuente
Algo que usan los ofuscadores: puede tener un campo / método / propiedad / evento que todos tengan el mismo nombre.
fuente
La herencia de enumeración no es realmente posible:
Puede heredar de una clase Enum. Pero el resultado no se comporta como un Enum en particular. Se comporta ni siquiera como un tipo de valor, sino como una clase ordinaria. Lo del rango es: IsEnum: True, IsValueType: True, IsClass: False
Pero eso no es particularmente útil (a menos que desee confundir a una persona o el tiempo de ejecución en sí).
fuente
También puede derivar una clase del delegado System.Multicast en IL, pero no puede hacer esto en C #:
fuente
También puede definir métodos de nivel de módulo (también conocido como global) en IL, y C #, por el contrario, solo le permite definir métodos siempre que estén asociados a al menos un tipo.
fuente