2008-08-26 6 views
42

vi un post acerca de características ocultas en C#, pero LINQ no mucha gente ha escrito ejemplo así que ... Me pregunto/lambdas ...El mejor truco de C# LINQ/Lambdas que alguna vez has sacado?

Lo que es el más fresco (como en el más elegante) el uso de la C# LINQ y/o Lambdas/delegados anónimos que hayas visto/escrito alguna vez?

¡Bonificación si también ha entrado en producción!

Respuesta

27

El LINQ Raytracer sin duda encabeza mi lista =)

No estoy muy seguro de si califica como elegante, pero es sin duda el más fresco LINQ expresión que he visto nunca!

Ah, y para ser extremadamente claro; Lo hice no escríbalo (Luke Hoban sí)

+1

me recuerda a la Madlebrot en SQL: http://thedailywtf.com/Articles/Stupid-Coding-Tricks-The-TSQL-Madlebrot.aspx – RHSeeger

+0

oí un podcast con Lucas, donde Estaba diciendo que usó la escritura de un rastreador de rayos para "probar" un nuevo idioma. Entonces, cuando apareció LINQ, simplemente aplicó su "prueba" estándar y nació el LINQ Raytracer. –

1

Estaba tratando de encontrar una forma genial de construir un control de navegación para un sitio web que estaba construyendo. Quería usar elementos de lista desordenada HTML regulares (empleando el estándar CSS "Sucker Fish" look) con un efecto de mouse de navegación superior que revela los elementos desplegables. Tenía un DataSet en caché dependiente de sql con dos tablas (NavigationTopLevels & NavigationBottomLevels). Entonces todo lo que tenía que hacer era crear dos objetos de clase (TopNav & SubNav) con las pocas propiedades requeridas (la clase TopNav tenía que tener una lista genérica de elementos bottomnav -> Lista <SubNav> SubItems).

 

var TopNavs = from n in ds.NavigationTopLevels select new TopNav { NavigateUrl = String.Format("{0}/{1}", tmpURL, n.id), Text = n.Text, id = n.id, SubItems = new List<SubNav>( from si in ds.NavigationBottomLevels where si.parentID == n.id select new SubNav { id = si.id, level = si.NavLevel, NavigateUrl = String.Format("{0}/{1}/{2}", tmpURL, n.id, si.id), parentID = si.parentID, Text = si.Text } ) }; List<TopNav> TopNavigation = TopNavs.ToList();

Tal vez no sea el más "cool", pero para una gran cantidad de personas que quieren tener la navegación dinámica, su dulce no tener que salir del todo en la lógica de bucle habitual que viene con eso. LINQ es, en todo caso, un ahorro de tiempo en este caso.

20

Algunos funcionales básicos:

public static class Functionals 
{ 
    // One-argument Y-Combinator. 
    public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F) 
    { 
     return t => F(Y(F))(t); 
    } 

    // Two-argument Y-Combinator. 
    public static Func<T1, T2, TResult> Y<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> F) 
    { 
     return (t1, t2) => F(Y(F))(t1, t2); 
    } 

    // Three-arugument Y-Combinator. 
    public static Func<T1, T2, T3, TResult> Y<T1, T2, T3, TResult>(Func<Func<T1, T2, T3, TResult>, Func<T1, T2, T3, TResult>> F) 
    { 
     return (t1, t2, t3) => F(Y(F))(t1, t2, t3); 
    } 

    // Four-arugument Y-Combinator. 
    public static Func<T1, T2, T3, T4, TResult> Y<T1, T2, T3, T4, TResult>(Func<Func<T1, T2, T3, T4, TResult>, Func<T1, T2, T3, T4, TResult>> F) 
    { 
     return (t1, t2, t3, t4) => F(Y(F))(t1, t2, t3, t4); 
    } 

    // Curry first argument 
    public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> F) 
    { 
     return t1 => t2 => F(t1, t2); 
    } 

    // Curry second argument. 
    public static Func<T2, Func<T1, TResult>> Curry2nd<T1, T2, TResult>(Func<T1, T2, TResult> F) 
    { 
     return t2 => t1 => F(t1, t2); 
    } 

    // Uncurry first argument. 
    public static Func<T1, T2, TResult> Uncurry<T1, T2, TResult>(Func<T1, Func<T2, TResult>> F) 
    { 
     return (t1, t2) => F(t1)(t2); 
    } 

    // Uncurry second argument. 
    public static Func<T1, T2, TResult> Uncurry2nd<T1, T2, TResult>(Func<T2, Func<T1, TResult>> F) 
    { 
     return (t1, t2) => F(t2)(t1); 
    } 
} 

no hacen mucho bueno si usted no sabe cómo usarlos. Con el fin de saber que, lo que necesita saber para qué son:

+3

¿Por qué esto todavía no es la funcionalidad estándar de .net? –

+0

Parece el método de extensión Zip() linq. – Larry

11

Progress Reporting de consultas LINQ larga duración. En la publicación del blog, puede encontrar un método de extensión WithProgressReporting() que le permite descubrir e informar el progreso de una consulta de linq mientras se ejecuta.

1

Creo que LINQ es un cambio importante en .NET y es una herramienta muy poderosa.

Uso LINQ to XML en producción para analizar y filtrar registros de un archivo XML de 6MB (con más de 20 niveles de nodos) en un conjunto de datos en dos líneas de código.

Antes de LINQ esto habría tomado cientos de líneas de código y días para depurar.

¡Eso es lo que yo llamo elegante!

+0

Seguro :-) Lo estoy amando. – chakrit

+0

Me pregunto por qué tuvimos que esperar tanto para que surgiera una tecnología como esta. – kahoon

0

Trabajar con atributos:

private void WriteMemberDescriptions(Type type) 
{ 
    var descriptions = 
     from member in type.GetMembers() 
     let attributes = member.GetAttributes<DescriptionAttribute>(true) 
     let attribute = attributes.FirstOrDefault() 
     where attribute != null 
     select new 
     { 
      Member = member.Name, 
      Text = attribute.Description 
     }; 

     foreach(var description in descriptions) 
     { 
      Console.WriteLine("{0}: {1}", description.Member, description.Text); 
     } 
} 

El método GetAttributes extensión:

public static class AttributeSelection 
{ 
    public static IEnumerable<T> GetAttributes<T>(this ICustomAttributeProvider provider, bool inherit) where T : Attribute 
    { 
     if(provider == null) 
     { 
      throw new ArgumentNullException("provider"); 
     } 

     return provider.GetCustomAttributes(typeof(T), inherit).Cast<T>(); 
    } 
} 

AttributeSelection es el código de producción y también define GetAttribute y HasAttribute. Elegí usar las cláusulas let y where en este ejemplo.

16

Con mucho, la más impresionante puesta en práctica de LINQ que he venir a través es el Brahma marco de referencia.

Se puede utilizar para descargar cálculos paralelos a la GPU usando 'Linq a GPU'. Usted escribe una 'consulta' en linq, y luego Brahma la traduce a HLSL (High Level Shader Language) para que DirectX pueda procesarla en la GPU.

Este sitio sólo me deja pegar un enlace a fin de tratar este webcast de dotnetrocks:

http://www.dotnetrocks.com/default.aspx?showNum=466

Else Google por Proyecto Brahma, obtendrá las páginas de la derecha.

Cosas realmente geniales.

GJ

+0

+1: Holy cr @ p! Eso es genial. Y malvado Muy malo. –

4

Para mí, la dualidad entre los delegados (Func<T,R>, Action<T>) y expresiones (Expression<Func<T,R>>Expression<Action<T>>) es lo que da origen a los usos más inteligentes de lambdas.

Por ejemplo:

public static class PropertyChangedExtensions 
{ 
    public static void Raise(this PropertyChangedEventHandler handler, Expression<Func<object>> propertyExpression) 
    { 
     if (handler != null) 
     { 
      // Retrieve lambda body 
      var body = propertyExpression.Body as MemberExpression; 
      if (body == null) 
       throw new ArgumentException("'propertyExpression' should be a member expression"); 

      // Extract the right part (after "=>") 
      var vmExpression = body.Expression as ConstantExpression; 
      if (vmExpression == null) 
       throw new ArgumentException("'propertyExpression' body should be a constant expression"); 

      // Create a reference to the calling object to pass it as the sender 
      LambdaExpression vmlambda = Expression.Lambda(vmExpression); 
      Delegate vmFunc = vmlambda.Compile(); 
      object vm = vmFunc.DynamicInvoke(); 

      // Extract the name of the property to raise a change on 
      string propertyName = body.Member.Name; 
      var e = new PropertyChangedEventArgs(propertyName); 
      handler(vm, e); 
     } 
    } 
} 

Entonces puede "segura" aplicar INotifyPropertyChanged llamando

if (PropertyChanged != null) 
    PropertyChanged.Raise(() => MyProperty); 

Nota: lo vi en la web en por primera vez hace un par de semanas, a continuación, pierde el enlace y una veintena de variaciones han surgido aquí y allá desde entonces, así que me temo que no puedo dar la atribución adecuada.

1

Quizás no sea el mejor, pero recientemente he estado usándolos cada vez que tengo un bloque de código que obtiene C + Pd una y otra vez solo para cambiar algunas líneas. Por ejemplo, los comandos que ejecuta SQL sencilla para recuperar datos puede hacerse de este modo:

SqlDevice device = GetDevice(); 

return device.GetMultiple<Post>(
    "GetPosts", 
    (s) => { 
     s.Parameters.AddWithValue("@CreatedOn", DateTime.Today); 

     return true; 
    }, 
    (r, p) => { 
     p.Title = r.Get<string>("Title"); 

     // Fill out post object 

     return true; 
    } 
); 

Lo que podría devolver una lista de mensajes que se crearon en la actualidad. De esta forma, no tengo que copiar y pegar el bloque try-catch-finally quince millones de veces para cada comando, objeto, etc.

Cuestiones relacionadas