Al igual que sucede en SQL, la clausula where se utiliza para filtrar el resultado de una lista de objetos.
La signatura de este operador es la siguiente:
1: public static IEnumerable<T> Where<T>(this IEnumerable<T> items,
2: Func<T, bool> predicate);
3: public static IEnumerable<T> Where<T>(this IEnumerable<T> items,
4: Func<T,int, bool> predicate);
En la segunda signatura se puede observar que tiene un parámetro más. Este parámetro de tipo int nos permitirá indicar porque elemento, porque index, de la colección queremos empezar a filtrar. Esto puede resultar muy útil a la hora de paginar una colección con un número elevado de elementos. La sintaxis sería la siguiente:
1: void list = _developers.Where((d,index) =>
2: d.Language == "C#" && index >= 1);
Ejemplos
Para la realización de los ejemplos se ha utilizado el siguiente código:
1: public class Developer
2: { 3: public string Name { get; set; } 4: public string Language { get; set; } 5: public int Age { get; set; } 6: }
7:
8: public List<Developer> developers = new List<Developer> { 9: new Developer{ Name="Jorge", Language="C#"}, 10: new Developer{ Name="Pedro", Language="C#"}, 11: new Developer{ Name="Raul", Language="VB.NET"}, 12: };
Ejemplos 1
1: var list = from d in developers
2: where d.Language == "C#"
3: select new { d.Name, d.Language };
Resultado:
Jorge C#
Pedro C#
Ejemplos 2
1: var list = from d in developers
2: where d.Language == "C#" && d.Name == "Pedro"
3: select new { d.Name, d.Language };
Resultado:
Pedro C#
Ejemplos 3
1: var list = developers.Where((d, index)
2: => (index >= start && index< end));
Resultado:
Pedro C#
Select
Al igual que ocurre en SQL las expresiones en LinQ se componen de varios partes. Una query típica tendrá una sentencia select ( select new { d.Name, d.Language } ), la cual será aplicada a una colección de elementos ( from d in _developers ) y estará a compañada de otras serie de elementos que nos permitirán filtrar el resultado de la query ( where d.Language == "C#" ), agruparla o simplemente ordenarla.
1: public static IEnumerable<S> Select<T, S>(this IEnumerable<T> source,
2: Func<T, S) selector;
3: public static IEnumerable<S> Select<T, S>(this IEnumerable<T> source,
4: Func<T,int, S) selector;
El código anterior muestra las dos posibles signaturas del método Select, que cómo se puede apreciar se tratan de Métodos Extendidos. Todas las operaciones que se pueden realizar en una query de LinQ están desarrolladas como Métodos Extendidos. Por este motivo, podríamos realizar operaciones como las siguientes:
1: var list = developers.Select(d => d.Name);
Una cosa curiosa de la sintaxis de las sentencias de LinQ es que la cláusula Select se coloca al final, evidentemente esto tiene su razón de ser. Seguido a la palabra Select se definen los campos que la query tiene que devolver. Si esta cláusula se colocase al principio, el compilador no sería capaz de inferir el tipo que se está utilizando en la sentencia. Por este motivo, en primer lugar se coloca la cláusua From, la cual sí define el tipo utilizando.
1: var list = from d in developers
2: select new { d.Name, d.Language }; 3:
4: var list = from d in developers
5: where d.Language == "C#"
6: select new { d.Name, d.Language };
SelectMany
Si por ejemplo quisiéramos obtener todos los nombres de los proyectos en los cuales los desarrolladores de C# han trabajada podríamos hacer esto:
1: var list = developers
2: .Where(d => d.Language == "C#")
3: .Select(d => d.Projects);
4:
5: var list = from d in developers
6: where d.Language == "C#"
7: select d.Projects;
Si hacemos esto, el resultado sería una lista y cada elemento de la lista sería un array de Projects ( IEnumerable< List<Project> > ). Más o menos era lo que queríamos, pero es mucho más interesante si nos devolvira una lista con todos los Projects insertados en ella directamente ( IEnumerable< Project > ). Aquí es donde entra en juego el método SelectMany. Las posibles signaturas de este método son las siguientes:
1: public static IEnumerable<S> SelectMany<T, S>(
2: this IEnumerable<T> source,
3: Func<T, IEnumerable<S>> selector);
4: public static IEnumerable<S> SelectMany<T, S>(
5: this IEnumerable<T> source,
6: Func<T, int, IEnumerable<S>> selector);
7: public static IEnumerable<S> SelectMany<T, S>(
8: this IEnumerable<T> source,
9: Func<T, IEnumerable<C>> collectionSelector,
10: Func<T, int, IEnumerable<S>> selector);
Para conseguir nuestro objetivo deberías desarrollar la query de una de las siguientes maneras, para así de esta forma conseguir una colección de Projects simple.
1: var list = developers.Where(d => d.Language == "C#")
2: .SelectMany(d => d.Projects);
3:
4: var list = from d in developers
5: where d.Language == "C#"
6: from p in d.Projects
7: select p;
Nota: Para la realización de estos ejemplo se han utilizado las siguientes entidades y colecciones.
1: public class Developer
2: { 3: public string Name { get; set; } 4: public string Language { get; set; } 5: public int Age { get; set; } 6: public List<Project> Projects { get; set; } 7: }
8:
9: public class Project
10: { 11: public string Name { get; set; } 12: }
13:
14: List<Developer> developers = new List<Developer> { 15: new Developer{ Name="Jorge", Language="C#", 16: Projects = new List<Project>{ 17: new Project{Name= "Sector7G"}, 18: new Project{Name= "LinQTool"} 19: }
20: },
21: new Developer{ Name="Pedro", Language="C#", 22: Projects = new List<Project>{ 23: new Project{Name= "Sector7G"}, 24: new Project{Name= "LinQTool"} 25: }
26: },
27: new Developer{ Name="Raul", Language="VB.NET", 28: Projects = new List<Project>{ 29: new Project{Name= "BlogSite"} 30: }
31: },
32: };
ASP.NET 2.0 ha introducido las masterpages en el desarrollo de aplicaciones, convirtiéndose en un recurso básico en el desarrollo web. Las masterpages presentaban una pequeña limitación ya que no era posible que una masterpages heredase de otra masterpage, bueno realmente si era posible, pero se pierde la vista de diseño pudiéndose convertir en un autentico infierno modificar el diseño de una página.

Visual Studio 2008 ya resuelve este problema. Haciendo posible que una masterpage herede de otra y se conserve la vista de diseño en la segunda masterpage. Mi primera masterpages, la cual contendrá el diseño común para toda la aplicación web sería la siguiente:

1: <%@ Master Language="C#" AutoEventWireup="true"
2: CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>
3: <html xmlns="http://www.w3.org/1999/xhtml">
4: <head runat="server">
5: <title>
6: Ejemplo MasterPages en Visual Studio 2008 Beta 2
7: </title>
8: </head>
9: <body>
10: <form id="form1" runat="server">
11: <div>MasterPage 1</div>
12: <div>
13: <asp:ContentPlaceHolder id="ContentPlaceHolder1"
14: runat="server">
15: </asp:ContentPlaceHolder>
16: </div>
17: </form>
18: </body>
19: </html>

1: <%@ Master Language="C#" MasterPageFile="~/MasterPage.master"
2: AutoEventWireup="false" CodeFile="MasterPage2.master.cs"
3: Inherits="MasterPage2" %>
4: <asp:Content ID="Content2"
5: ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
6: <div>
7: MasterPage 2
8: </div>
9: <asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
10: </asp:ContentPlaceHolder>
11: </asp:Content>
Al página aspx sería la siguiente:

1: <%@ Page Language="C#" MasterPageFile="~/MasterPage2.master"
2: AutoEventWireup="true" CodeFile="Default.aspx.cs"
3: Inherits="_Default" Title="Untitled Page" %>
4: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder2"
5: Runat="Server">
6: <p>Esta es la página por defecto.</p>
7: </asp:Content>
Otra cosa curiosa de la nueva versión del editor de código fuente de C# es la organización de Usings. Esta característica no estaba disponible en Visual Studio .Net 2005, pero herramientas como Resharper ya lo soportaban y yo personalmente la echaba de menos. Básicamente de lo que se trata es de poder borrar los usings que realmente no se utilicen en el código y de ordenarlos alfabéticamente.
Veamos un ejemplo.
1: using System;
2: using System.Text;
3: using System.Collections.Generic;
4: using System.IO;
5: using System.Data.Sql;
6: using System.Collections;
7: using System.Globalization;
Ordenando la lista de usings.

1: using System;
2: using System.Collections;
3: using System.Collections.Generic;
4: using System.Data.Sql;
5: using System.Globalization;
6: using System.IO;
7: using System.Text;
Borrando los usings que no se utilizan en el código fuente:
Ya me he instalado la beta 2 de Visual Studio 2008 y buscando pijadillas he encontrado una curiosa. Ahora con la nueva versión del IDE se puede seleccionar el cualquier framework que tengas instalado para compilar las aplicaciones.
Para poder seleccionar el framework sólo hay que ir a las propiedades del proyecto, ahí hay un combo donde se muestran todos los frameworks instalados en el equipo de desarrollo. Seleccionas la que más te guste y listo.

Una cosa curiosa que he visto que se puede hacer, es que diferentes proyectos de una misma solución se pueden compilen para el uso de diferentes framework. Por ejemplo, si en una solución tenemos un proyecto de consola y una librería, podríamos hacer que el proyecto de consola se compilara para el .Net Framework 3.5 y la librería para el .Net Framework 2.0. Lo compilas y evidentemente funciona correctamente, pero me parece no menos que curioso.