[Pregunta] Sobre métodos extensores II

Dada la siguiente clase:

public class Striker
{
    public string Name { get; set; }
    public int  Goals { get; set; }
    public Look Looks { get; set; }
}
 


public enum Look
{
    Handsomd,
    Ugly
}

Creamos un método extensor Where:

public static class Extensions
{
    public static IEnumerable<Striker> Where(
        this IEnumerable<Striker> source,
        Func<Striker, bool> filter)
    {
        foreach (var striker in source)
        {
            if (filter(striker) && (striker.Looks == Look.Handsomd))
                yield return striker;
        }
    }
}

Y probamos:

class Program
{
    static void Main(string[] args)
    {
        var strikers = new[] {
            new Striker { Name = "Ronaldo", Looks = Look.Handsomd, Goals = 46},
            new Striker { Name = "Messi", Looks = Look.Ugly, Goals = 50},
            new Striker { Name = "Falcao", Looks = Look.Ugly, Goals = 26}
         };
 
        var result = strikers.Where(s => s.Goals > 40);
 
        foreach (var striker in result)
        {
            Console.WriteLine(striker.Name);
        }
 
        Console.Read();
    }
}

¿Cual creéis que será la salida?

Un saludo

Published 18/5/2012 13:04 por Luis Ruiz Pavón
Archivado en:
Comparte este post:
http://geeks.ms/blogs/lruiz/archive/2012/05/18/pregunta-sobre-m-233-todos-extensores-ii.aspx

Comentarios

# re: [Pregunta] Sobre métodos extensores II

Buenas!

Pues yo creo que te devolverá un solo resultado (no diré cual).

Pero la forma en como se está usando este enum no me cuadra nada, pero nada de nada.

Saludos!

Friday, May 18, 2012 1:20 PM por Eduard Tomàs i Avellana

# re: [Pregunta] Sobre métodos extensores II

Fixit!

Thanks!

Friday, May 18, 2012 1:40 PM por Luis Ruiz Pavón

# re: [Pregunta] Sobre métodos extensores II

Pue sí señor, un solo resultado, el siguiente balón de oro "Ronaldo"

La cosa es ver que si creamos un método extensor como en este caso Where, que ya existe en el espaciod e nombres System.Linq, tiene preferencia los métodos extensores de nuestro espacio de nombres. Así que hay que tener cuidado :)

Un saludp

Friday, May 18, 2012 1:45 PM por Luis Ruiz Pavón

# re: [Pregunta] Sobre métodos extensores II

xDDD

Vale, ahora entiendo el motivo del post :P

Aunque, si me permites, una puntualización :)

Tu método Where es tomado en lugar del método Where de LINQ, simple y llanamente porque NO es genérico.

Un método NO genérico siempre tiene prioridad sobre uno de genérico.

class Program

{

   static void Foo<T>(T t)

   {

       Console.WriteLine(typeof(T).Name);

   }

   static void Foo(int i)

   {

       Console.WriteLine("Es un entero!");

   }

   static void Main(string[] args)

   {

       Foo(10);

       Console.Read();

   }

}

La salida de este programa es "Es un entero!". Porque el método Foo(int) tiene más prioridad que el método Foo<T> siendo T = int.

Pues lo mismo ocurre en tu caso.

Saludos!!!

Friday, May 18, 2012 1:51 PM por Eduard Tomàs i Avellana

# re: [Pregunta] Sobre métodos extensores II

Hola un mini aporte más XDD

Aunque lo declares como generico:

public static IEnumerable<T> Where<T>(

           this IEnumerable<T> source,

           Func<T, bool> filter)

Al menos en las pruebas que he estado haciendo, invoca a tu propio método, pero creo que si incluyeras una clausula where:

public static IEnumerable<T> Where<T>(

           this IEnumerable<T> source,

           Func<T, bool> filter)  where T : IPlayer

Llamaria a tu método. ¿Qué opinas Edu?

Friday, May 18, 2012 2:28 PM por Javier Torrecilla

# re: [Pregunta] Sobre métodos extensores II

Efectivamente Javier como decía más arriba:

"tiene preferencia los métodos extensores de nuestro espacio de nombres"

Da igual que sean genéricos o no :)

Un saludo

Friday, May 18, 2012 2:48 PM por Luis Ruiz Pavón

# re: [Pregunta] Sobre métodos extensores II

y yo digo... ¿que pasa si ponemos esta línea de código Luis?:

var result = strikers.Where<Striker>(s => s.Goals > 40);

En lugar de:

var result = strikers.Where(s => s.Goals > 40);

Pruébalo. ;)

Friday, May 18, 2012 3:04 PM por Jorge Serrano

# re: [Pregunta] Sobre métodos extensores II

Buena apreciación Jorge :)

Ronaldo

Messi

Usa el System.Linq ¿Por qué?

Un saludo

Friday, May 18, 2012 3:14 PM por Luis Ruiz Pavón

# re: [Pregunta] Sobre métodos extensores II

Porque en el caso de Jorge, estás invocando al método genérico, ya que pones específicamente un tipo genérico (<Striker>), con lo cual el compilador DEBE invocar un método genérico, y el tuyo no lo es.

Ahora bien, si el método Where que hubiera definido Luis fuese:

public static class Extensions

{

   public static IEnumerable<T> Where<T>(

       this IEnumerable<T> source,

       Func<T, bool> filter)

   {

       foreach (var striker in source)

       {

           if (filter(striker) )

               yield return striker;

       }

   }

}

En este caso, si este método está dentro del mismo namespace que el que lo invoca SI se usa este método en lugar del de LINQ. Este caso SI es a lo que se refería Luis con lo de "tiene preferencia los métodos extensores de nuestro espacio de nombres". Pero NO es el mimso caso que ha expuesto en el post. En el post su método se selecciona porque NO es genérico. Y se seleccionaría ANTES que el de LINQ incluso aunque NO estuviese en el mismo namespace.

Javi, que haya una cláusula where NO implica nada. Nada de nada. Haz una prueba rápida: crea el método genérico ese, con la clausula. Mételo dentro de un namespace foo.

Añade el using System.Linq y el using foo. Llama a .Where y verás que el código NO compila.

Hay un post de eric lippert donde lo cuenta: las cláusulas where NO forman parte de la firma: blogs.msdn.com/.../constraints-are-not-part-of-the-signature.aspx

Saludos!

Friday, May 18, 2012 3:58 PM por Eduard Tomàs i Avellana

# re: [Pregunta] Sobre métodos extensores II

Exacto!!! Esa es la razón, o al menos, así lo veo yo también. :)

Friday, May 18, 2012 5:17 PM por Jorge Serrano

# re: [Pregunta] Sobre métodos extensores II

Muy buenos los comentarios, sobre todo porque uso mucho los métodos y a veces me veo con estos temas. Muy buenos

Friday, May 18, 2012 6:10 PM por Xavi Paper

# re: [Pregunta] Sobre métodos extensores II

Por cierto Eduard, entiendo que con tu último comentario, lo que quieres indicar es que la llamada adecuada sería entonces algo así:

var result = strikers.Where(s => s.Goals > 40 && s.Looks == Look.Handsomd);

Y en el caso habitual:

var result = strikers.Where(s => s.Goals > 40);

De esta manera, obtendríamos las dos salidas que indicaba Luis.

¿Es así?.

Un saludo,

Jorge

Friday, May 18, 2012 7:15 PM por Jorge Serrano