[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

12 comentarios sobre “[Pregunta] Sobre métodos extensores II”

  1. 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!

  2. 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

  3. xDDD
    Vale, ahora entiendo el motivo del post 😛

    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)
    {
    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 siendo T = int.
    Pues lo mismo ocurre en tu caso.

    Saludos!!!

  4. Hola un mini aporte más XDD

    Aunque lo declares como generico:

    public static IEnumerable Where(
    this IEnumerable
    source,
    Func
    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 Where(
    this IEnumerable
    source,
    Func
    filter) where T : IPlayer

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

  5. 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

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

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

    En lugar de:

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

    Pruébalo. 😉

  7. Porque en el caso de Jorge, estás invocando al método genérico, ya que pones específicamente un tipo genérico (), 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 Where(
    this IEnumerable
    source,
    Func
    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: http://blogs.msdn.com/b/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx

    Saludos!

  8. 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

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *