domingo, 12 de julio de 2015

Atributos en C#

Índice

0. Introducción
1. ¿Qué son los Atributos?
2. ¿Cómo Usar un Atributo?
3. Uso Efectivo de un Atributo
4. Especificación de Múltiples Atributos
5. Atributos Personalizados
6. Restricción de Atributos a Determinados Elementos de Programa
7. Atributos  con Parámetros Nombrados y Posicionales
8. Conclusiones
9. Glosario
10. Literatura & Enlaces

0. Introducción

Un nuevo artículo de C# avanzado sobre la utilidad y uso de atributos. Los atributos, como ya veremos con más precisión, permiten marcar una clase, método, assembly, namespace, etc. con determinadas características que atribuyen o restrigen comportamiento al elemento de programa. En este artículo C#, exploraremos: por qué son necesarios, utilidad, algunas clases de atributos definidas en .NET Framework, atributos personalizados, parámetros de atributos, entre otros más. Escribiremos código C# para entender su utilidad, e inclusive veremos cómo en Visual Studio 2013 IntelliSense es capaz de mostrar mensajes en tiempo de diseño y compilación acerca del uso correcto de atributos.

1. ¿Qué son los Atributos?

Los atributos son etiquetas o marcas especificadas en determinados elementos de programa (e.g., clases, métodos, propiedades, assemblies, nombre de espacio) [3]. Estas etiquetas o marcas definen nuevo comportamiento para el elemento de programa marcado. E inclusive, permite establecer restricciones; como por ejemplo la obsolescencia de un método en futuras versiones de una librería.

Los atributos también se pueden entender como un mecanismo de extensión de comportamiento declarativo flexible, es decir, sin requerir estructuras programáticas complejas [1].

2. ¿Cómo Usar un Atributo?

A nivel declarativo, un atributo se especifica antecediendo un elemento de programa. El atributo se ha de especificar entre los caracteres sintácticos [ (paréntesis rectangular de apertura) y ] (paréntesis rectangular de cierre). Así:

[NombreAtributo([parámetros])]
ElementoPrograma

Descripción:
  • NombreAtributo es el nombre del atributo que deseamos aplicar a ElementoPrograma.
  • Parámetros: Conjunto de parámetros asociados al atributo. (Opcionales).
  • ElementoPrograma: Se refiere a a cualquier clase, método, atributo, nombre de espacio, assembly, etc.

3. Uso Efectivo de Atributos

Asumamos que hemos desarrollado una librería en C# que actualmente cuenta con varias versiones en uso: 1, 2, y 3. Varios de los elementos de la versión 1 ya son obsoletos en la versión 2 y 3, sin embargo siguen estando presentes. ¿Cómo podemos declarativamente marcar o etiquetar esos elementos de programa como obsoletos sin necesidad de escribir código adicional o removerlos del código de nuevas versiones?

Usar atributos es la respuesta a esta pregunta. Supongamos que contamos con la clase Email:

public class Email
{
[Absolete]
public bool ComprobarEmail()
{
// Implementación versión 1.
}

public bool ValidarEmail()
{
// Implementación versiones 2, y 3.
}
}

Notemos cómo hemos marcado el método ComprobarEmail con el atributo Absolete. (Absolete es uno de los atributos de la librería común de .NET.)

Ahora desde código cliente, ¿cómo nos informamos que el método ComprobarEmail es obsoleto? Veamos:

Archivo C# Email.cs [Enlace alternativo]:

En la línea 7 hemos usado el atributo AbsoleteAttribute para marcar el método ComprobarEmail (líneas 8-12) como obsoleto en las versiones 2 y 3 de nuestra librería. Cuando compilamos este programa, el compilador C# mostrará la siguiente advertencia:

Email.cs(29, 3): warning CS0612: `Email.ComprobarEmail()` is obsolete


Lo cual indica que este método es obsoleto. En Visual Studio 2013, IntelliSense nos muestra este diálogo emergente de información para darnos a entender que el método que pretendemos usar es obsoleto (deprecated):
Mensaje de advertencia por IntelliSense en Visual Studio
Figura 1. Mensaje de advertencia por IntelliSense en Visual Studio.

4. Especificación de Múltiples Atributos

También es posible marcar un elemento de programa con múltiples atributos. Estas son las formas posibles:

1. Cada atributo separado por coma dentro del mismo par de paréntesis rectangulares:

[Serializable, Obsolete, CLSCompliant(false)]
public class ClienteEntity
{...}

2. Cada atributo en un par de paréntesis:

[Serializable] [Obsolete] [CLSCompliant(false)]
public class ClienteEntity
{...}

3. Combinación de atributos por par de paréntesis:

[Serializable, Obsolete○]
[CLSCompliant(false)]
public class ClienteEntity
{...}


Todas estas definiciones son equivalentes.

5. Atributos Personalizados

En la sección 3 vimos cómo usar el atributo AbsoleteAttribute de la BCL sobre un método. No sólo podemos usar los atributos definidos en esta librería, también podemos definir los nuestros propios. Lo que tenemos hacer, en esencia, es lo siguiente:
  1. Crear una clase.
  2. Hacer que esta clase herede de Attribute [4] (namespace System) directa o indirectamente.
  3. Seleccionar la clase o cualquier otro elemento de programa donde deseamos aplicar el atributo.
class Autor : Attribute
{
public String m_nombre;
public double m_version;

public Autor(String nombre)
{
this.m_nombre = nombre;
this.m_version = 1.0;
}
}

Una vez definido el atributo Autor ya podemos marcar un elemento de programa, por ejemplo una clase, para establecer su autoría:

[Autor("John Ortiz", version=1.1)]
public class Email
{
// implementación
}

Como observamos este atributo, Autor, nos permite establecer la autoría sobre un elemento de programa. Dentro de los paréntesis rectangulares escribimos el nombre del autor, y la versión para el código.

5. Restricción de Atributos a Determinados Elementos de Programa

En la definición de un nuevo atributo podemos establecer restricciones sobre los elementos de programa que tendrá efecto el atributo; esto lo logramos a través AttributeUsage [5] y la enumeración AttributeTargets [6]:

[AttributeUsage(AttributeTargets.Method)]
public class NuevoAtributo : Attribute
{}


Aplicamos el atributo a la clase NuevaClase:

[NuevoAtributo]
public class NuevaClase {...}

Cuando intentemos compilar un programa con la declaración anterior, en Visual Studio se generá el siguiente error en tiempo de compilación:


Attribute `NuevoAtributo` is not valid on this declaration type. It is only valid on 'method' declarations.
Mensaje de error al tratar de usar el atributo `NuevoAtributo` sobre una clase
Figura 2. Mensaje de error al tratar de usar el atributo NuevoAtributo sobre una clase.

En la Animación 1 se muestran las restricciones posibles sobre elementos de programa que ofrece la enumeración AttributeTargets.
Elementos de programa restrictivos por `AttributesUsage`
Animación 1. Elementos de programa restrictivos por AttributesUsage.

7. Atributos  con Parámetros Nombrados y Posicionales

Los parámetros de un atributo se categorizan en:
  • nombrados, o 
  • posicionales.
Tomemos como ejemplo la siguiente declaración:

[XmlElement ("Cliente", Namespace="http://ortizol.blogspot.com")]
public class ClienteEntity
{
// Implementación...
}

El primer parámetro, Cliente, es un atributo posicional e indica que la clase ClienteEntity será asociado/mapeada a la entidad XML Cliente. Los atributos posicionales son obligatorios.

En cuanto a los atributos nombrados, como lo es Namespace, en el ejemplo anterior se da entender que el elemento XML Cliente pertenece al namespace http://ortizol.blogspot.com. Los atributos nombrados son opcionales, además.

8. Conclusiones

Hemos estudiado atributos en C# como medio declarativo para la extensión de comportamiento de clases, métodos, propiedades, y otros elementos de programa. Notamos que la sintaxis declarativa es simple y directa: en esencia, basta con marcar el elemento precedido por un par de paréntesis rectangulares y enlistar los atributos junto con los parámetros nombrados y posicionales según sea necesario. Vimos, además, que es posible restringir la aplicación de un atributo a determinados elementos de programa a través de AttributeUsage y la enumeración AttributeTargets (que admite operaciones bitwise).


En el próximo artículo C# estudiáremos otra aplicación de los atributos: marca de los parámetros de un método.

9. Glosario

  • Atributo
  • Bitwise
  • C#
  • Comilador
  • Parámetro nombrado
  • Parámetro posicional
  • XML

10. Literatura & Enlaces

[1]: C# 5.0 in a Nutshell by Joseph Albahari and Ben Albahari. Copyright 2012 Joseph Albahari and Ben Albahari, 978-1-449-32010-2.
[2]: C# Attributes in 5 minutes - CodeProject - http://www.codeproject.com/Articles/827091/Csharp-Attributes-in-minutes
[3]: Introduction to Attributes (C#) - https://msdn.microsoft.com/en-us/library/aa288059(v=vs.71).aspx
[4]: Attribute Class (System) - https://msdn.microsoft.com/en-us/library/system.attribute(v=vs.110).aspx
[5]: AttributeUsage (C# and Visual Basic) - https://msdn.microsoft.com/en-us/library/tw5zxet9.aspx
[6]: AttributeTargets Enumeration (System) - https://msdn.microsoft.com/en-us/library/system.attributetargets.aspx


J

No hay comentarios:

Publicar un comentario

Envíe sus comentarios, dudas, sugerencias, críticas. Gracias.