Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

18 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 23 de septiembre de 2014
En posts anteriores hemos hablado del operador de navegación segura “.?” y de la inicialización de propiedades automáticas, y vamos a comentar ahora otra de las novedades de la versión de C# que viene en camino, pero que en esta ocasión no tengo claro que sea un avance en la dirección correcta. Os lo cuento y ya decidís vosotros ;-)

Hay escenarios en los que en el interior de una clase utilizamos de forma intensiva miembros estáticos de otras clases. Un ejemplo habitual podemos encontrarlo en componentes que hagan mucho uso de System.Math para la realización de cálculos matemáticos, o incluso en el conocido System.Console:




Pues bien, en C# 6 podremos indicar mediante un using que vamos a realizar llamadas a miembros estáticos de la clase que indiquemos, por lo que no será necesario especificarla en cada llamada:



Internamente, cuando el compilador encuentra esas llamadas a WriteLine() o ReadLine(), determinará que pertenecen al objeto System.Console porque no existe ningún otro candidato más apropiado que las implemente. Si la propia clase Program dispusiera de un método estático WriteLine(), se habría utilizado éste.

También se tienen en cuenta casos en los que la llamada pudiera resultar ambigua para evitar. Por ejemplo, si estamos haciendo un using de dos clases que implementan un método estático con el mismo nombre y signatura, el compilador se quejará y tendremos que referenciarlas de forma explícita, como hemos hecho hasta ahora.

Ciertamente usando esta característica podemos ahorrar muchas pulsaciones de teclas, así como hacer más claro nuestro código… ¿o no? El problema lo veo justamente ahí: en la claridad. Aunque visualmente el código resulta menos denso y más fácil de leer, estamos incluyendo un cierto grado de “ofuscación” (por llamarlo de alguna forma) que puede complicar la comprensión de lo que se hace o dónde se hace. Por ejemplo, fijaos en las llamadas que se realizan desde el siguiente método:



Podemos ver que usamos muchos métodos matemáticos y por tanto sería un caso de uso de esta nueva característica del lenguaje, pero en un vistazo no se sabríamos quién los está implementando. En versiones de C# anteriores a la 6, podríamos asegurar que Sinh(), Pow(), Sqr() o Floor() son miembros de la clase actual o algunas de sus antecesoras, pero en la nueva versión un using System.Math al principio del archivo podría invalidar esta afirmación.

De hecho, ni aún existiendo ese  using System.Math  podríamos estar seguros de dónde se encuentra definido un método, porque podríamos tener una implementación local a la clase del mismo que sería la utilizada aunque a nivel de código no quede explícitamente indicado. Y también puede dar lugar a confusiones casos como la llamada a Sqr() del código anterior porque, aunque parezca lo contrario, no existe en System.Math (el método que realmente existe es  Sqrt()).

En fin, supongo que ocurre como con muchas otras características del lenguaje, que no son de por sí buenas ni malas: todo depende del uso que se les dé. Probablemente hacer un uso razonable de esta característica en un contexto concreto y acotado podría ser útil para ahorrarnos trabajo, pero no tengo claro si el coste en términos de legibilidad compensará en muchos casos.

Ya con el tiempo, cuando vea cómo se utiliza y los problemas que crea en proyectos reales igual cambio de idea, pero de momento pienso que se podían haber ahorrado el esfuerzo.

Publicado en Variable not found.

5 Comentarios:

Baldomero dijo...

Es una opción desastrosa que resta información y dificulta la lectura del código. Esto suena a que ya no saben qué inventar.

Juanma dijo...

No deja de ser exactamente la misma pérdida de información que al usar un extension method (pierdes el nombre de la clase en que está definida un método estático).

Supongo que habrá contextos en que ayuden más o menos, pero no creo que sea "una opción desastrosa".

En java existen los static imports desde hace mucho tiempo y se usan bastante, por ejemplo, para "limpiar" de ruido los asserts en los tests.

Sergio León dijo...

Pues a priori diría que parece ofuscar en cierta forma el código, pero después del comentario de Juanma ya no estoy tan seguro de que no tenga alguna utilidad para casos concretos :)
Imagino que la característica en sí misma no es mala, será en todo caso malo el uso indebido que hagamos de ella... vamos, que no he dicho nada que aporte valor al post! :)
Un saludo.

josé M. Aguilar dijo...

Gracias a todos por comentar :)

@Juanma, totalmente cierto lo que dices. La sensación en cuanto a la pérdida de visión es muy parecida a los métodos extensores, y los "peligros" que puede acarrear su uso son muy similares.

Y comparto tu visión sobre su utilidad: hay escenarios en los que ahorrará mucha tecla y facilitará la lectura. Siempre que se use con cordura y se atienda al "principio de mínima sorpresa", no debería ser un problema, el problema vendrá cuando su uso sea inapropiado, como todo en esta vida :)

@Sergio, está claro, no es la herramienta, es el uso que demos a la misma el que la hará buena o mala. Ah, y tu participación siempre aporta, amigo ;)

Saludos!

LuisLAP dijo...

Como siempre, cuando se agrega una nueva funcionalidad (azúcar sintático) generalmente lo vemos como malo, porque no estamos acostumbrados, porque va "contra lo que yo hago", porque "no me parece útil", etc.

La importación de clases estáticas es muy útil, y dependiendo de cómo codifiques, es más útil aun.

Un ejemplo perfecto es si has decidido desarrollar utilizando la programación funcional (que sería un buen tema para una entrada en el blog), donde se pueden importar los métodos estáticos de una o mas clases estáticas y utilizarlos en el código, eso evita muchísimo código pues no hay que escribir el nombre de la case estática, que al final de cuentas poco interesa si se desarrolla de forma funcional.

Otro ejemplo es cuando tenemos código en clases estáticas como por ejemplo enumeradores, o constantes. Llenar el código de nombres de clase solo para utilizar sus miembros "ensucia" el código. Recordemos que el mismo intellisense de VS nos proporciona información sobre la clase y hasta el namespace de donde proviene el objeto.