You are on page 1of 8

acaNovedades c# 3.

Inferencia de tipos de variables locales:

Ahora se puede deducir el tipo de una variable según el valor que se le asigna, usando la
palabra clave var.
Declarar una variable con var, hará que el tipo de dicha variable sea inferido del tipo
resultante de la expresión a la que dicha variable se inicialice (esto... sigue siendo C#,
eh?). El tipo de la variable una vez inferido no puede ser modificado;

ANTES AHORA

string nombre = “diego”; var nombre = “diego”;


int edad = 25; var edad = 25;
bool varon = true; var varon = true;

También se puede usar con colecciones:

 var numbers = new int[] { 1, 2, 3, 4, 5}


 var people = new List<Person>();
 var a = new[] { 1, 2, 3, 4, 5, 6 };
 var b = new[] { 1, 2.5, 3.2, 4.1 };
 var c = new [] { “hola”, “don”, “pepito” };

Tipos anónimos:

Los tipos anónimos son una característica que permite a los desarrolladores definir los
tipos en el código, sin tener que declarar una clase explícita. Aunque se pueden usar en
muchos escenarios, son particularmente útiles cuando usamos LINQ.

var persona =new{


id = 123;
nombre = “diego”;
edad = 25;
baron = true; }

En el ejemplo, el compilador parseará la sintaxis anterior y definirá automáticamente un


tipo del CLR con cuatro propiedades. El tipo de cada una de esas cuatro propiedades
estan determinadas por el tipo de inicialización que tengan cada una (por ejemplo, en el
ejemplo anterior a la propiedad “Id” se le asigna un entero - así que el compilador
generará la propiedad el mismo patrón IL que hubiera generado si la hubiesemos
declarado explícitamente como entero.

El nombre actual del CLR para el tipo anónimo será generado por el compilador de C#.
En realidad el CLR no sabe la diferencia entre un tipo anónimo y tipo no anónimo - así
que la semántica de los dos casos son exáctamente iguales.

Si escribieramos “persona.” en el tipo anónimo, seguimos teniendo soporte para el


intelisense y chequeo en tiempo de compilación en Visual Studio.

El uso de tipos anónimos es perfecto para conseguir estructuras de datos con una
cantidad mínima de código, y es particularmente útil cuando consultamos y
transformamos/incrustamos datos con LINQ.

var persona ={
from p in db.Persona;
select p;
}

Inicialización de objetos

Los tipos del .NET Framework confían ciegamente en el uso de propiedades. Cuando
instanciamos y usamos clases nuevas, es muy común escribir código como este:

Person person = new Person();


person.FirstName = “Scott”;
person.LastName = “Guthrie”;
person.Age = 32;

¿Habéis querido hacer esto de una forma más clara (o quizás en sólo una línea)?. Con
los compiladores de Orcas para C# y VB, podemos usar una característica llamada
“inicializadores de objetos” (en ingles: “object initializers”) que nos permite hacer lo
que comentamos y reescribir el código anterior de la siguiente forma:

Person person = new Person { FirstName=“Scott”, LastName=“Guthrie”, Age=32 };

El compilador generará automáticamente el código de inicialización necesario


guardando el mismo significado semántico que en la primera versión (más arriba) del
código de ejemplo. Pero no sólo nos permite inicializar un objeto con valores simples,
esta nueva característica nos permite poner valores más complejos como propiedades
anidadas. Por ejemplo, imaginemos que en la clase Person también tenemos una
propiedad llamada “Address” del tipo “Address”. Podríamos escribir el siguiente código
para crear un objeto del tipo Person y poner sus propiedades de la siguiente forma:
Person person = new Person {
FirstName = “Scott”,
LastName = “Guthrie”
Age = 32,
Address = new Address {
Street = “One Microsoft Way”,
City = “Redmond”,
State = “WA”,
Zip = 98052
}
};
Los inicializadores de objetos están bien, y hacen mucho más claro añadir objetos a
colecciones de objetos. Por ejemplo, si queremos añadir tres personas a una lista
genérica de tipo Person. Podemos escribirlo de la siguiente forma:

List<Person> people = new List<Person>();

people.Add( new Person { FirstName = “Scott”, LastName = “Guthrie”, Age = 32 } );


people.Add( new Person { FirstName = “Bill”, LastName = “Gates”, Age = 50 } );
people.Add( new Person { FirstName = “Susanne”, LastName = “Guthrie”, Age = 32 } );

Usando los inicializadores de objetos sólo ahorramos 12 líneas de código extra en este
ejemplo en comparación con lo que hubiésemos necesitado con el compilador de C#
2.0.

Los compiladores de Orcas para C# y VB nos permiten mucho más, y ahora soportan
los “inicializadores de colecciones” (en inglés: “collection initializers”) que nos
permiten evitar tener varias llamadas al método Add, y ahorrarnos aún más tecleo:

List<Person> people = new List<Person> {


new Person { FirstName = “Scott”, LastName = “Guthrie”, Age = 32 },
new Person { FirstName = “Bill”, LastName = “Gates”, Age = 50 },
new Person { FirstName = “Susanne”, LastName = “Guthrie”, Age = 32 }
};

Cuando el compilador encuentra un código como este último, generará el código


necesario para añadir los diferentes elementos a la colección.

Resumen

Como desarrolladores tenemos una nueva forma para hacer nuestro código más conciso
a la hora de definir objetos, inicializarlos y añadirlos a colecciones. En ejecución, la
semántica será exactamente la misma que la que tenemos con la sintaxis más larga de
hoy. (Así que no tenemos que preocuparnos por cambios en el comportamiento). No
necesitamos escribir tanto por lo que nuestro código será más corto.
Propiedades automáticas

Las propiedades automáticas nos permiten evitar la declaración manual de variables


privadas y escribir el código de los métodos get/set – En lugar de eso, el compilador
puede crear automáticamente las variables privadas necesarias y el código por defecto
de los métodos get/set por nosotros.

Lo que antes se declararía de la siguiente manera:

public class Person


{
private string _firstName;

public string FirstName


{
get {
return _firstName;
}
set {
firstName = value;
}
}
}

Ahora podemos hacerlo de esta:

public class Person


{
public string FirstName {get; set;}
}

Cuando el compilador de Orcas de C# se encuentre con los Get/Set’s vacíos, como en el


código anterior, generará automáticamente una variable privada en la clase, e
implementará las propiedades públicas get y set para ella. El beneficio de esto es que
desde un punto de vista de tipo-contrato, la clase será exactamente igual que la primera
implementación de la que hablábamos más arriba. Esto significa que –al contrario que
las variables públicas – más adelante podemos añadir validación lógica en el método set
sin tener que cambiar ningún componente externo que referencie a mi clase.

Métodos de extensión (en Ingles: Extension Methods).

¿Qué son los métodos de extensión?

Los métodos de extensión permiten a los desarrolladores añadir nuevo métodos al


contrato público de un tipo ya existente en el CLR, sin tener que recompilar el tipo
original.
Los métodos de extensión posibilitan la aparición de una gran variedad de escenarios , y
ayudan a hacer posible el poder del framework LINQ que va a ser añadido a .NET como
parte de la release de Orcas.

Ejemplo de un método de extensión simple:

¿No habéis querido chequear si un string es una dirección válida de email? Hoy,
implementaríamos esto llamando a una clase a parte (seguramente con un método
estático) para ver si el string es válido. Por ejemplo, algo así:

string email = Request.QueryString[“email”];


if ( EmailValidator.IsValid(email) )
{

Usando métodos de extensión podríamos añadir un método “IsValidEmailAddress()”


dentro de la propia clase string, y devolverá cierto o falso dependiendo de si la dirección
es válida o no. De esta forma, podríamos hacer lo de arriba con el siguiente código:

string email = Request.QueryString[“email”];


if ( email.IsValidEmailAddress() )
{

Pero, ¿cómo añadimos este nuevo método, IsValidEmailAddress(), a la clase string?. Lo


hicimos definiendo una clase estática con un método estático que contiene nuestro
método de extensión IsValidEmailAddress() de la siguiente forma:

public static class ScottGuExtensions


{
public static bool IsValidEmailAddress(this string s)
{
Regex regex = new Regex(@”^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$”);
return regex.IsMatch(s);
}
}

Daros cuenta que en el parámetro de entrada del método está la palabra “this”, antes que
el parámetro de tipo string. Esto le dice al compilador que este método de extensión
debe ser añadido a objetos de tipo string. Dentro del cuerpo del método
IsValidEmailAddress() podemos acceder a todas las propiedades/métodos/eventos
públicos de la instancia del string actual, y devolver true/false dependiendo de si es un
email válido o no.

Para añadir este método de extensión específico a las instancias de string de mi código,
sólo usamos un “using” estándar para importar el namespace que contiene la
implementación de los métodos de extensión:

using ScottGuExtensions;
El compilador resolverá correctamente el método IsValidEmailAddress() en cualquier
string. C# y VB dan soporte completo para el intellisense de los métodos de extensión
en el editor de Visual Studio. De manera que cuando pulsamos el “.” en una variable
string, los métodos de extensión que hayamos implementado, se mostrarán en la lista
del intellisense.

Centrándonos en los métodos de extensión para añadir métodos a tipos existentes,


podemos abrir una gran variedad de escenarios posibles para los desarrolladores. Lo que
realmente hace a los métodos de extensión una herramienta prodigiosa no es sólo poder
ser aplicada a tipos individuales, sino a cualquier clase padre o interface del .NET
Framework. Esto permite a los desarrolladores construir una variedad casi infinita de
extensiones que se pueden usar en todo el .NET Framework.

Por ejemplo, imaginemos que quiero comprobar de forma fácil y descriptiva si un


objeto está añadido en una colección o array de objetos. Podemos añadir un simple
método de extensión .In(collection) que quiero que se añada a todos los objetos de .NET
para poder hacer eso. Podemos implementar este método de extensión “In()” en C# de
la siguiente forma:

public static class ScottGuExtensions


{
public static bool In(this object o, IEnumerable c )
{
Foreach (object i in c)
{
If (i.Equals(o))
{
return true;
}
}
}
}

Fijaos cómo he declarado el primer parámetro para el método de extensión es “this


object o”. Esto indica que este método de extensión debe ser aplicado a todos los tipos
que hereden de la clase base System.Object – esto significa que puedo usar este método
en cualquier objeto en .NET.

La implementación del método “In()” de arriba, nos permite ver si un objeto específico
está incluido en una secuencia IEnumerable que se le pasa como argumento. Debido a
que todas las colecciones de .NET implementan la interfaz IEnumerable, hemos
conseguido un método útil y descriptivo para comprobar si cualquier objeto de .NET
pertenece a cualquier colección o tabla de .NET.

Podemos usar este método de extensión “In()” para comprobar si un string en particular
está en un array de strings, incluso podemos comprobar si un control de ASP .NET está
en un contenedor de controles.

Como podéis empezar a discernir de los ejemplos de arriba, los métodos de extensión
nos abren escenarios muy ricos y posibilidades de extensibilidad. Cuando se aplican a
clases comunes y a interfaces en .NET nos habilitan frameworks de dominio específicos
muy curiosos.

Expresiones Lambda.

¿Qué son las Expresiones Lambda?

Concepto de métodos anónimos, que permiten que los bloques del código sean escritos
“en línea” donde se esperan los valores del delegado.

C#2.0 ( que venía con VS 2005) introdujo el concepto de métodos anónimos, que
permitía escribir bloques de código donde se esperaban delegados.
// Manera anónima, nos ahorramos el button1_Click que llame a Funciona.
this.button1.Click += delegate { this.Funcion(); };

Las Expresiones Lambda aportan una sintaxis más concisa y funcional para escribir
métodos anónimos. Son extremadamente útiles cuando escribimos peticiones LINQ -
permiten una forma muy compacta de escribir funciones que puedan ser pasadas como
argumentos para una evaluación posterior.

Explicaciones de las expresiones Lambda.

La forma más sencilla para conceptualizar las expresiones lambda es pensar en ellas
como formas de escribir métodos breves en una linea.

En C# una expresión lambda es escrita, sintácticamente, como una lista de parámteros,


seguido del token “=>”, y seguido por una expresión o un bloque de sentencias para que
se ejecuten cuando se invoque la expresión

params =>expression

Así, cuando escribimos la expresión lambda:

p=>p.LastName==”Guthrie”

Estamos indicando que la expresión lambda que estamos definiendo recibe un


parámetro “p”, y que la expresión del código que se va a ejecutar devuelve el valor
p.LastName que sea igual a “Guthrie”. El echo de que llamemos “p” al parámetro es
irrelevante - podria haberlo llamado “o”, “x”, “foo” o cualquier nombre que hubiese
querido.
Al contrario que con los métodos anónimos, que requieren declaraciones de los tipos de
los parametros explícitamente, las expresiones Lambda permiten omitir los tipos de los
parámetros dejando que se infieran basándose en su uso.
Los tipos de parametros Lambda pueden ser inferidos tanto en tiempo de compilación y
por el motor de intellisense de Visual Studio (esto significa que tenemos soporte
completo de intellisense cuando estamos escribiendo expresiones lambda).

Nota: Si queréis declarar explícitamente el tipo del parametro de una expresión Lambda,
podeis hacerlo declarando el tipo del parámetro ántes del nombre del parámetro de la
siguiente forma:

Resumen:

Cuando se combinan las expresiones Lambda con los métodos de extensión de LINQ,
nos ofrece una forma muy rica de consultar e interactuar con cualquier tipo de datos
conservando el soporte en tiempo de compilación e intellisense.

You might also like