Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anterior Revisión previa Próxima revisión | Revisión previa | ||
|
highlevel:chsarp:versions [2009/03/18 10:59] alfred |
highlevel:chsarp:versions [2020/05/09 09:25] (actual) |
||
|---|---|---|---|
| Línea 180: | Línea 180: | ||
| ===== C# 3.0 ===== | ===== C# 3.0 ===== | ||
| + | |||
| + | |||
| ==== Propiedades autoimplementables ==== | ==== Propiedades autoimplementables ==== | ||
| Línea 188: | Línea 190: | ||
| public string Name { get; private set; } // read-only | public string Name { get; private set; } // read-only | ||
| public int CustomerID { get; private set; } // read-only | public int CustomerID { get; private set; } // read-only | ||
| + | } | ||
| + | </code> | ||
| + | Podemos crear una lista de elementos con propiedades autoimplementables de la forma siguiente: | ||
| + | <code csharp> | ||
| + | class Person { | ||
| + | public string firstName { get; set; } | ||
| + | public int age { get; set; } | ||
| + | } | ||
| + | class Program { | ||
| + | static void Main(string[] args) { | ||
| + | List<Person> people = new List<Person> { | ||
| + | new Person { firstName = "Juan", age = 33 }, | ||
| + | new Person { firstName = "Pedro", age = 14 }, | ||
| + | new Person { firstName = "MaryCury", age = 25} | ||
| + | }; | ||
| + | } | ||
| } | } | ||
| </code> | </code> | ||
| + | |||
| + | ==== Tipos implícitos ==== | ||
| + | Es una forma de "esquivar" la declaración del tipo de una variable. Esto va muy bien cuando el tipo de la variable tiene una forma compleja (genéricos, query variables (en LINQ)...). \\ \\ | ||
| + | Para declarar una variable con tipado implícito se utiliza la clausula ''var''. | ||
| + | <code csharp> | ||
| + | var myList = new List<int>(); | ||
| + | myList.Add( 1 ); | ||
| + | myList.Add( 2 ); | ||
| + | myList.Add( 3 ); | ||
| + | foreach( var i in myList ) | ||
| + | Console.WriteLine( i ); | ||
| + | </code> | ||
| + | |||
| + | También podemos asigndar directamente el valor y la variable tomará el tipo de dicho valor: | ||
| + | <code csharp> | ||
| + | var i = 10; | ||
| + | Console.WriteLine("El tipo de i es: {0} ({1})", i.GetType().Name, i); | ||
| + | </code> | ||
| + | O... | ||
| + | <code csharp> | ||
| + | SqlCommand cmd = new SqlCommand("select * from personas", con); | ||
| + | var dr = cmd.ExecuteReader(); | ||
| + | </code> | ||
| + | |||
| + | Pero no podemos declarar una variable con tipado implícito sin indicar el valor, por ejemplo el siguiente código daría error: | ||
| + | <code csharp> | ||
| + | var variable; | ||
| + | </code> | ||
| + | |||
| + | ==== Métodos de extensión ==== | ||
| + | Permiten añadir nuevos métodos a clases ya existentes sin tener que recompilar. | ||
| + | Para utilizarlos lo que haremos será crear una clase estática con un método estático de un único parámetro, si antes de la definición del tipo de dicho parámetro colocamos la palabra 'this' el método pasará a ser un método de extensión para los objetos del mismo tipo que el parámetro: | ||
| + | <code csharp> | ||
| + | static class MyExtensions { | ||
| + | public static bool isValidEmail(this string str) { | ||
| + | return true; | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | Ahora dicho método puede ser utilizado en los objetos de este tipo: | ||
| + | <code csharp> | ||
| + | string str = ""; | ||
| + | str.isValidEmail(); | ||
| + | </code> | ||
| + | Si la clase no pudiese ser accedida (debido a que está en otro namespace o librería necesitaríamos utilizar la clausula 'using': | ||
| + | <code csharp> | ||
| + | using MyExtensions; | ||
| + | </code> | ||
| + | Si quisieramos que se pudiese pasar algún argumento a este método entonces añadiremos otro parámetro al método de extensión: | ||
| + | <code csharp> | ||
| + | public static bool isIn(this string str, IEnumerable<string> col) | ||
| + | { | ||
| + | foreach (string s in col) | ||
| + | if (s.CompareTo(str) == 0) | ||
| + | return true; | ||
| + | return false; | ||
| + | } | ||
| + | // Y luego... | ||
| + | List<string> lStr = new List<string> { "Hi", "Hello", "Bon Journo" }; | ||
| + | string str = "Hola"; | ||
| + | str.isIn(lStr); | ||
| + | </code> | ||
| ==== Expresiones Lambda ==== | ==== Expresiones Lambda ==== | ||
| - | Una expresión lambda consiste en: | + | Son expresiones que pueden ser asignadas como funciones simples. Una expresión lambda consiste en: |
| - Una lista de parámetros, entre parentesis (a no ser que sólo fuese uno). Pueden ser explícitamente tipados (indicando el tipo) o implícitamente tipados). | - Una lista de parámetros, entre parentesis (a no ser que sólo fuese uno). Pueden ser explícitamente tipados (indicando el tipo) o implícitamente tipados). | ||
| - El token ''<nowiki>=></nowiki>''. | - El token ''<nowiki>=></nowiki>''. | ||
| - Una expresión o sentencia. | - Una expresión o sentencia. | ||
| - | <code> | + | <code csharp> |
| (int x) => x + 1; // Explícitamente tipado | (int x) => x + 1; // Explícitamente tipado | ||
| (x,y) => x * y; // Implícitamente tipado | (x,y) => x * y; // Implícitamente tipado | ||
| x => x + 1; // Implícitamente tipado, un sólo parámetro | x => x + 1; // Implícitamente tipado, un sólo parámetro | ||
| </code> | </code> | ||
| + | Por ejemplo la expresión lambda ''x => x + 1'' significa "toma x como argumento y devuelve el resultado de la operación con x". \\ | ||
| + | Las expresiones lambda pueden ser asignadas a delegados para darles cuerpo. Por ejemplo el delegado ''TResult System.Func<T, TResult>''define una función que recibe como parámetro un tipo T y devuelve un tipo TResult. \\ | ||
| + | Cuando el compilador asigna la expresión lambda a una variable delegado se usa el tipo indicado para determinar el tipo de los parámetros de la función lambda. \\ | ||
| + | En el siguiente vemos como utilizar una variable delegado mediante métodos anónimos y mediante una expresión lambda: | ||
| + | <code csharp> | ||
| + | Func<string, string> convert = delegate(string s) { return s.ToUpper();}; | ||
| + | Func<string, string> convertLambda = s => s.ToUpper(); | ||
| + | |||
| + | string name = "Dakota"; | ||
| + | Console.WriteLine(convert(name)); | ||
| + | Console.WriteLine(convertLambda(name)); | ||
| + | </code> | ||
| + | Las listas utilizan en varios métodos este delegado para realizar operaciones sobre los datos que contienen, aquí es donde pueden ser explotadas este tipo de expresiones: | ||
| + | <code csharp> | ||
| + | IEnumerable<Person> p = people.Where(x => x.age < 30); // Retorna una lista con los elementos Person que tengan una age menor de 30 | ||
| + | people.Average(x => x.age); // Retorna la media de age de todos los elementos dentro de people | ||
| + | </code> | ||
| + | Otro ejemplo que utiliza una lambda expression un poco más compleja: | ||
| + | <code csharp> | ||
| + | int[] source = new[] { 3, 8, 4, 6, 1, 7, 9, 2, 4, 8 }; | ||
| + | foreach (int i in source.Where( | ||
| + | x => { | ||
| + | if (x <= 3) | ||
| + | return true; | ||
| + | else if (x >= 7) | ||
| + | return true; | ||
| + | return false; | ||
| + | } | ||
| + | )) | ||
| + | Console.WriteLine(i); | ||
| + | </code> | ||
| + | Otra funcionalidad útil es la recursividad anónima. Por ejemplo una expresión lambda que retorne el factorial de un número: | ||
| + | <code csharp> | ||
| + | Func<int, int> fact = null; | ||
| + | fact = (x) => x > 1 ? x * fact(x-1) : 1; | ||
| + | </code> | ||
| + | |||
| + | En la versión 3.0 del framework se han agregado métodos de extensión para colecciones que aprovechan el poder de las expresiones lambda. Por ejemplo el siguiente método myWhere: | ||
| + | <code csharp> | ||
| + | static class myExtensions { | ||
| + | public static List<T> myWhere<T>(this IEnumerable<T> source, Func<T,bool> question) { | ||
| + | List<T> list = new List<T>(); | ||
| + | foreach (T element in source) | ||
| + | if (question(element)) | ||
| + | list.Add(element); | ||
| + | return list; | ||
| + | } | ||
| + | } | ||
| + | </code> | ||
| + | Devuelve una nueva lista con los elementos de la lista sobre la que sea llamado que en el parámetro question (que puede ser una expresión lambda) devuelvan true: | ||
| + | <code csharp> | ||
| + | List<Person> myList = lPerson.myWhere(p => p.age < 30); | ||
| + | </code> | ||
| + | === Expression Trees === | ||
| + | |||
| + | |||
| + | |||
| + | |||
| ==== LINQ ==== | ==== LINQ ==== | ||
| + | LINQ da de forma nativa expresiones para describir operanciones sobre datos que no han sido modelados de forma orientada a objetos (por ejemplo, crear expresiones que busquen en un array de elementos ubicado en memoria) a partir de cierto patrón. También puede ser extensible a otros campos (including LINQ to SQL (DLINQ), LINQ to Dataset, LINQ to Entities, LINQ to XML (XLINQ), o LINQ to Objects) siempre y cuando los elementos se encuentren una clase que extienda ''IEnumerable''. \\ \\ | ||
| + | * [[fw:othersnet:linq|Apartado general sobre LINQ]]. | ||
| + | * [[fw:othersnet:dlinq|Apartado general sobre DLINQ (LINQ to SQL)]]. | ||