lunes, 28 de mayo de 2007

C# 3.0

Krlo [blackhat4all@gmail.com]

Muchos expertos han subvalorado las mejoras de C# 3.0; aseguran que sus nuevas ofertas no son más que azúcar sintáctica. Lo cierto es que esta nueva versión es mucho más versátil y está orientada a aliviarle la vida al desarrollador, aún más que las anteriores. Con este artículo pretendo acercarlos a las principales mejoras del mismo. Algunas, por razones de espacio, serán más resumidas.

Las principales innovaciones son:

  • Variables de tipo implícito
  • Tipos Anónimos
  • Inicializadores de objetos y colecciones
  • Métodos de Extensión
  • Expresiones Lambda
  • Expresiones de Pregunta (Query Expressions)
  • Arrays de Tipo Implícito
  • Arboles de Expresión
  • Variables de tipo implicito.

Se introduce la nueva palabra clave var, la cual permite declarar nuevas variables, cuyo tipo se infiere implícitamente de la expresión usada para inicializar la variable. Ejemplo:

var i = 1;
var intArr = new[] {1,2,3,4};

Para asegurar que se cumpla en todo momento con la seguridad de tipos, C# require que se inicialice la variable después de declararla (var i; explotaría sin remedio). A esta forma de reconocer implícitamente el tipo de un objeto se le verá su extraordinario aporte más adelante.

Tipos Anonimos (TA):

C# 3.0 brinda la flexibilidad de crear instancias de una clase sin haberlas definido.

var Anon = new {hair="black", skin="green", teethCount=64};

Vendría siendo igual a:

class Anonymous1
{
  private string _hair = "black";
  private string _skin = "green";
  private int _teeth = 64;
  public string hair {get {return _hair;} set {_hair = value;}}
  public string skin {get {return _skin;} set {_skin = value;}}
  public int teeth {get {return _teeth; } set {_teeth = value; }}
}

Un inicializador de objeto anónimo declara un tipo anónimo y devuelve una instancia de ese tipo. Un tipo anónimo hereda directamente de object. Como pudimos observar, un TA es una secuencia de propiedades de lectura/escritura inferidas del inicializador o inicializadores de objeto.

El nombre de un tipo anónimo es generado automáticamente por el compilador y no puede ser referenciado en el texto del programa. Dentro del mismo programa, dos inicializadores de objetos anónimos que especifiquen una secuencia de propiedades de los mismos nombres y tipos en el mismo orden producirán instancias del mismo tipo anónimo. En concreto:

var p1 = new {Name = "Lawnmower", Price = 495.00};
var p2 = new {Name = "Shovel", Price = 26.95};
p1 = p2;
//esto es totalmente válido

Inicializadores de objetos y colecciones:

Antes:

public class CoOrdinate{
  public int x ;
  public int y;
}

Ahora podemos declarar e inicializar un objeto CoOrdinate de la siguiente manera:

var myCoOrd = new CoOrdinate{x = 0, y = 0}; //aquí se infiere hasta el tipo int de x y y.

Para trabajar con colecciones:

List<string> animals = new List<string>();
animals.Add("monkey");
animals.Add("donkey");
animals.Add("cow");
animals.Add("dog");
animals.Add("cat");

Ahora para simplificar podemos hacer:

List<string> animals = new List<string> {"monkey", "donkey", "cow", "dog", "cat"};

Esto es como un objeto List que creamos tan fácilmente como hacemos con un array de strings. Una colección se entiende en este contexto como un tipo que implementa System.Collections.Generic.ICollection<T> para exactamente una T.

Los Metodos de Extensión:

Los métodos extendidos posibilitan extender varios tipos con métodos estáticos adicionales (importante lo de estático). Sin embargo, ellos son muy limitados y deben ser usados como un último recurso, sólo cuando los métodos de instancia son insuficientes. Los métodos extendidos pueden ser declarados sólo en clases estáticas y son definidos por la palabra clave this como un modificador en el primer parámetro del método. A continuación un ejemplo de un método extendido válido:

public static int ToInt32(this string s)
{
  return Convert.ToInt32(s);
}

Si la clase estática que contiene el método antes expuesto es importada usando la palabra clave using. El método ToInt32 aparecerá en los tipos existentes (a pesar de esto es de poca preferencia con respecto a métodos de instancia existentes) y se podrá compilar y ejecutar código como el siguiente:

string s = "1";
int i = s.ToInt32();

Esto nos permite tomar ventaja de la naturaleza extensible de varios tipos internos definidos y agregar nuevos métodos al mismo. Todos los objetos tienen el método ToString(). No te gustaría que la clase String tuviera los métodos: ToInt(), ToDouble() o TodoLoQueSea(). Esta opción creo que eriza a todos los que nos gusta manosear código.

Expresiones lambda:

C# 2.0 introdujo los métodos anónimos que permitían escribir bloques de código “en línea” donde valores delegados eran esparcidos, pero la sintaxis era verbosa e imperativa. Las expresiones lambda son una forma más concisa de escribir métodos anónimos. En C# 1.x los delegados se trataban de la siguiente manera:

class Program{
  delegate void DemoDelegate();
  static void Main(string[] args) {
    DemoDelegate myDelegate = new DemoDelegate(SayHi);
    myDelegate();
  }
  void SayHi(){
    Console.Writeline("Hiya!!") ;
  }
}

En C# 2.0, usando métodos anónimos, podemos escribir lo mismo un poco más cómodo:

class Program{
  delegate void DemoDelegate();
  static void Main(string[] args){
    DemoDelegate myDelegate = delegate(){Console.Writeline("Hiya!!");};
    myDelegate() ;
  }
}

Podemos escribir expresiones lambda como una lista de parámetros, seguidos del token =>, y un bloque de expresiones o sentencias:

class Program{
  delegate void DemoDelegate();
  static void Main(string[] args){
    DemoDelegate myDelegate = () => Console.WriteLine("Hiya!!") ; //que creen.
    myDelegate();
  }
}

Las expresiones lambda ofrecen las siguientes funcionalidades adicionales:

  • Permiten que los tipos de los parámetros sean inferidos. Los métodos anónimos requerían explícitamente los tipos de sus parámetros.
  • Pueden soportar también expresiones Query.
  • Pueden ser tratadas como datos usando árboles de expresión.

Arrays de Tipos Implícitos:

La sintaxis para crear arrays se ha extendido para soportar la creación de arrays de tipo implícito.

var a = new[] {1, 10, 100, 1000}; // int[]
var b = new[] {1, 1.5, 2, 2.5}; // double[]
var c = new[] {"hello", null, "world";}; // string[]
var d = new[] {1, "one", 2, "two"}; // Error, no se puede convertir int a string o al revés.

Se atreven a combinar esta técnica con objetos anónimos:

var contacts = new[] {
  new {Name = "Krlo", PhoneNumbers = new[] {"55-55-55", "07708-73"}},
  new {Name = "Alien", PhoneNumbers = new[] {"650-555-0199"}}
};

El que no se acostumbre a escribir comentarios va a pasar trabajo. Esto, un poco más complicado, a la semana no hay Dios que lo entienda.

Expresiones de Pregunta (Query Expressions):

Esta innovación ofrece una sintaxis integrada en el lenguaje para consultas, similar a los lenguajes de consulta relacionales y jerárquicos, como SQL y XQuery. No domino bien el SQL, pero les aseguro que este punto es muy ventajoso, sobre todos para quienes trabajan con bases de datos.

Arboles de Expresión (AE):

Los Expression Trees permiten a las expresiones lambda ser representadas como estructuras de datos en lugar de código ejecutable. En otras palabras, logran que expresiones sean tratadas como datos en tiempo de ejecución. El objetivo es poder modificar y examinar expresiones lambda en tiempo de ejecución. Los AE son objetos de tipo System.Expressions.Expression<T>.

Conclusiones:

Traté de ser breve en todo momento. Espero que les haya servido de background para cuando tengan al esperado personaje. La versión final 3.0 de .NET Framework está cada vez más cerca (ya está disponible la Pre-Release). La mejora fundamental del Framework 3.0 serán las bibliotecas para programar formularios Windows Vista con estilo 3D, es decir mayor uso de las transparencias, efectos gráficos más vistosos y un mayor uso de la tarjeta gráfica. Recordar que todas estas opciones se pueden desactivar y correr un Windows Vista con aspecto "normal" pero con mejoras significativas sobre la seguridad y estabilidad.

¿Y ORCAS? El entorno de desarrollo será Visual Studio 2005, parece que Visual Studio 2007 o ORCAS tardará todavía un poco en salir e incluirá de serie las bibliotecas para trabajar con LINX, el "nuevo" lenguaje XML para datos (¿quién se embulla a hablar de LINX o Ajax en BlackHat?). Esta versión traerá soporte total para las bibliotecas WinFX (esto es como la API de Vista).

Para saber más...



Artículos relacionados


No hay comentarios: