¿Cómo se hacen las "funciones en línea" en C #? No creo entender el concepto. ¿Son como métodos anónimos? ¿Te gustan las funciones lambda?
Nota : Las respuestas tratan casi por completo de la capacidad de incorporar funciones en línea , es decir, "una optimización manual o de compilación que reemplaza un sitio de llamada de función con el cuerpo del destinatario". Si está interesado en funciones anónimas (también conocidas como lambda) , consulte la respuesta de @ jalf o ¿De qué se trata esta 'Lambda' de la que todos hablan? .
c#
optimization
inline
Dinah
fuente
fuente
Respuestas:
Finalmente en .NET 4.5, el CLR le permite a uno insinuar / sugerir 1 método en línea usando el
MethodImplOptions.AggressiveInlining
valor. También está disponible en el maletero del Mono (comprometido hoy).1 . Anteriormente "fuerza" se usaba aquí. Como hubo algunos votos negativos, intentaré aclarar el término. Al igual que en los comentarios y la documentación,
The method should be inlined if possible.
especialmente teniendo en cuenta Mono (que está abierto), existen algunas limitaciones técnicas monoespecíficas que consideran la inclusión en línea o una más general (como funciones virtuales). En general, sí, esto es una pista para el compilador, pero supongo que eso es lo que se pidió.fuente
Los métodos en línea son simplemente una optimización del compilador donde el código de una función se incluye en la persona que llama.
No hay ningún mecanismo para hacer esto en C #, y se deben usar con moderación en los lenguajes donde son compatibles; si no sabe por qué deberían usarse en algún lugar, no deberían serlo.
Editar: para aclarar, hay dos razones principales por las que deben usarse con moderación:
Es mejor dejar las cosas en paz y dejar que el compilador haga su trabajo, luego perfile y descubra si en línea es la mejor solución para usted. Por supuesto, algunas cosas simplemente tienen sentido estar en línea (operadores matemáticos en particular), pero dejar que el compilador lo maneje suele ser la mejor práctica.
fuente
Actualización: Por la respuesta de konrad.kruczynski , lo siguiente es cierto para las versiones de .NET hasta e incluyendo 4,0.
Puede usar la clase MethodImplAttribute para evitar que un método se inserte ...
... pero no hay forma de hacer lo contrario y forzarlo a estar en línea.
fuente
GetExecutingAssembly
yGetCallingAssembly
puede dar resultados diferentes dependiendo de si el método está en línea. Forzar que un método no esté en línea elimina cualquier incertidumbre.Estás mezclando dos conceptos separados. La función en línea es una optimización del compilador que no tiene impacto en la semántica. Una función se comporta igual si está en línea o no.
Por otro lado, las funciones lambda son puramente un concepto semántico. No hay ningún requisito sobre cómo deben implementarse o ejecutarse, siempre y cuando sigan el comportamiento establecido en la especificación del lenguaje. Pueden estar en línea si el compilador JIT lo desea, o no si no lo hace.
No hay una palabra clave en línea en C #, porque es una optimización que generalmente se puede dejar al compilador, especialmente en los lenguajes JIT. El compilador JIT tiene acceso a estadísticas de tiempo de ejecución que le permiten decidir qué incluir en línea de manera mucho más eficiente que cuando escribe el código. Una función estará en línea si el compilador lo decide, y no hay nada que pueda hacer al respecto de ninguna manera. :)
fuente
¿Te refieres a las funciones en línea en el sentido de C ++? ¿En qué los contenidos de una función normal se copian automáticamente en línea en el sitio de llamadas? El efecto final es que no se produce ninguna llamada a la función cuando se llama a una función.
Ejemplo:
Si es así, entonces no, no hay C # equivalente a esto.
¿O quiere decir funciones que se declaran dentro de otra función? Si es así, sí, C # admite esto mediante métodos anónimos o expresiones lambda.
Ejemplo:
fuente
Cody tiene razón, pero quiero proporcionar un ejemplo de lo que es una función en línea.
Digamos que tienes este código:
El optimizador Just-In-Time del
compiladorpodría elegir alterar el código para evitar hacer una llamada repetida a OutputItem () en la pila, de modo que sería como si hubiera escrito el código de esta manera:En este caso, diríamos que la función OutputItem () estaba en línea. Tenga en cuenta que podría hacerlo incluso si se llama a OutputItem () desde otros lugares también.
Editado para mostrar un escenario con más probabilidades de estar en línea.
fuente
Sí. Exactamente, la única distinción es el hecho de que devuelve un valor.
Simplificación (sin usar expresiones):
List<T>.ForEach
Toma una acción, no espera un resultado de retorno.Entonces un
Action<T>
delegado sería suficiente ... diga:es lo mismo que decir:
la diferencia es que el tipo de parámetro y la declinación delegada se infieren por el uso y no se requieren llaves en un método simple en línea.
Donde como
List<T>.Where
Toma una función, esperando un resultado.Entonces
Function<T, bool>
se esperaría un:que es lo mismo que:
También puede declarar estos métodos en línea y asignarlos a las variables IE:
o
Espero que esto ayude.
fuente
Hay ocasiones en las que deseo forzar el código para que esté alineado.
Por ejemplo, si tengo una rutina compleja donde hay una gran cantidad de decisiones tomadas dentro de un bloque altamente iterativo y esas decisiones resultan en acciones similares pero ligeramente diferentes que se llevarán a cabo. Considere, por ejemplo, un comparador de clasificación complejo (no basado en DB) donde el algoritmo de clasificación clasifica los elementos de acuerdo con una serie de criterios diferentes no relacionados, como uno podría hacer si clasificaran las palabras de acuerdo con criterios gramaticales y semánticos para un lenguaje rápido sistema de reconocimiento Tendería a escribir funciones auxiliares para manejar esas acciones con el fin de mantener la legibilidad y la modularidad del código fuente.
Sé que esas funciones auxiliares deberían estar alineadas porque esa es la forma en que se escribiría el código si un humano nunca tuviera que entenderlo. Ciertamente, me gustaría asegurarme en este caso de que no haya ninguna función llamando a la sobrecarga.
fuente
La afirmación "es mejor dejar estas cosas en paz y dejar que el compilador haga el trabajo ..." (Cody Brocious) es una completa tontería. He estado programando código de juego de alto rendimiento durante 20 años, y todavía tengo que encontrar un compilador que sea 'lo suficientemente inteligente' como para saber qué código debe estar integrado (funciones) o no. Sería útil tener una declaración "en línea" en C #, la verdad es que el compilador simplemente no tiene toda la información que necesita para determinar qué función debe estar siempre en línea o no sin la pista "en línea". Claro, si la función es pequeña (accesor), entonces podría estar en línea automáticamente, pero ¿qué pasa si se trata de unas pocas líneas de código? Nonesense, el compilador no tiene forma de saberlo, no puede dejar eso en manos del compilador para obtener un código optimizado (más allá de los algoritmos).
fuente
Sé que esta pregunta es sobre C #. Sin embargo, puede escribir funciones en línea en .NET con F #. ver: Uso de `en línea` en F #
fuente
No, no existe tal construcción en C #, pero el compilador .NET JIT podría decidir hacer llamadas de función en línea en tiempo JIT. Pero en realidad no sé si realmente está haciendo tales optimizaciones.
(Creo que debería :-))
fuente
En caso de que sus ensamblajes sean ngen-ed, es posible que desee echar un vistazo a TargetedPatchingOptOut. Esto ayudará a ngen a decidir si utilizar métodos en línea. Referencia de MSDN
Sin embargo, todavía es solo una pista declarativa para optimizar, no un comando imperativo.
fuente
¡Las expresiones lambda son funciones en línea! ¡Creo que C # no tiene un atributo adicional como en línea o algo así!
fuente
C # no admite métodos en línea (o funciones) en la forma en que lo hacen los lenguajes dinámicos como python. Sin embargo, los métodos anónimos y las lambdas se pueden usar para fines similares, incluso cuando necesita acceder a una variable en el método que contiene, como en el ejemplo a continuación.
fuente