2010-07-15 18 views
9

de Jon Skeet maravilloso libro C# en profundidad, Primera Edición:jugar con los tipos anónimos

class Film 
{ 
    public string Name { get; set; } 
    public int Year { get; set; } 

    public override string ToString() 
    { 
     return string.Format("Name={0}, Year={1}", Name, Year); 
    } 
} 

var films = new List<Film> 
{ 
    new Film {Name="Jaws", Year=1975}, 
    new Film {Name="Singing in the Rain", Year=1952}, 
    new Film {Name="Some Like It Hot", Year=1959}, 
    new Film {Name="The Wizard of Oz", Year=1939}, 
    new Film {Name="It's a Wonderful Life", Year=1946}, 
    new Film {Name="American Beauty", Year=1999}, 
    new Film {Name="High Fidelity", Year=2000}, 
    new Film {Name="The Usual Suspects", Year=1995} 
}; 

Action<Film> print = film => { Console.WriteLine(film); }; 
films.ForEach(print); 
films.FindAll(film => film.Year < 1960) 
.ForEach(print); 
films.Sort((f1, f2) => f1.Name.CompareTo(f2.Name)); 
films.ForEach(print); 

Un párrafo sigue el fragmento anteriormente enumerados de código.

La primera mitad del listado 9.4 consiste simplemente en configurar los datos. Hubiera usado un tipo anónimo, pero es relativamente complicado crear una lista genérica a partir de una colección de instancias de tipo anónimo. (Puede hacerlo por creando un método genérico que tome una matriz y la convierta en una lista del mismo tipo, luego pase una matriz tipada implícitamente en ese método . Un método de extensión en .NET 3.5 llamado ToList proporciona esto funcionalidad también, pero eso sería hacer trampa ya que no hemos mirado a los métodos de extensión todavía!)

Y el fragmento de código proporcionado anteriormente, está enumerando 9.4 del libro que el párrafo se refiere a.

Mi pregunta: Estoy probando la técnica descrita en el párrafo anterior con la mano (mira el texto en cursiva), pero no acabo de entender lo que quiere decir.

he intentado algo como esto, pero no es lo que quería decir, supongo, ya que no funciona (y yo no esperaba que a):

using System; 
using System.Collections.Generic; 

namespace ScratchPad 
{ 

class Film 
{ 
    public string Name { get; set; } 
    public int Year { get; set; } 

    public override string ToString() 
    { 
     return string.Format("Name = {0}\tYear = {1}", 
      Name, Year); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     ToList<Film>(new[] 
     { 
      new { Name = "North By Northwest", Year = 1959 }, 
      new { Name = "The Green Mile", Year = 1999}, 
      new { Name = "The Pursuit of Happyness", Year = 2006} 
     }).ForEach(f => {Console.WriteLine(f);}); 

     Console.ReadKey(); 
    } 

    static List<T> ToList<T>(
     System.Collections.IEnumerable list) 
    { 
     var newList = new List<T>(); 

     foreach (var thing in list) 
      if (thing is T) 
       newList.Add((T)thing); 

     return newList; 

    } 
} 

}

Nota: Conozco el método de extensión IEnumerable.ToList() y lo he usado muchas veces. Solo quiero probar la técnica delineada en el párrafo a mano.

Además, me intrigan los escenarios en los que se usan tipos anónimos fuera de Linq, como una conveniencia sintáctica y uno de estos escenarios se detalla a continuación. Siempre puedo usar dynamic en C# 4 y aceptar un tipo anónimo como argumento y trabajar con él sabiendo lo que espero. Me gustaría poder hacer eso con C# 3. Algo parecido a continuación:

using System; 
using Microsoft.CSharp.RuntimeBinder; 

namespace PlayWithAnonType 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      PrintThingy(new { Name = "The Secret", 
Genre = "Documentary", Year = 2006 }); 
      Console.ReadKey(); 
     } 

    static void PrintWhatever(dynamic whatever) 
    { 
     // the anonymous type's ToString() will print 
     Console.WriteLine(whatever); 
    } 

    static void PrintThingy(dynamic thingy) 
    { 
     try 
     { 
      // I know what the thingy is 
      Console.WriteLine("Name = {0}\tGenre = {1}\tYear = {2}", 
       thingy.Name, thingy.Genre, thingy.Year); 
     } 
     catch(RuntimeBinderException ex) 
     { 
#pragma warning disable 0168 
      Console.WriteLine("By thingy, I really meant film. 
Sorry, I should've clarified."); 
#pragma warning restore 0168 
     } 
    } 
} 

}

Editar Ellos deben tener una etiqueta llamado Jon-skeet.

+1

Sé quién va a ganar esta pregunta;) – Skurmedel

+0

Sería muy irónico si se le hiciera una pregunta sobre el libro de Jon, Jon asintió y otra persona ganó jaja – Icemanind

+0

@Skurmedel He he he! –

Respuesta

6

es hacerlo realidad:

public void Main (string[] args) 
{ 
    var films = ToList(new [] { 
     new {Name = "Jaws", Year = 1975}, 
     new {Name = "Singing in the Rain", Year = 1952}, 
     new {Name = "Some Like It Hot", Year = 1959}, 
     new {Name = "The Wizard of Oz", Year = 1939}, 
     new {Name = "It's a Wonderful Life", Year = 1946}, 
     new {Name = "American Beauty", Year = 1999}, 
     new {Name = "High Fidelity", Year = 2000}, 
     new {Name = "The Usual Suspects", Year = 1995} 
    } 
    ); 


    films.ForEach(f => Console.Write(f.Name + " - " + f.Year)); 

} 

public List<T> ToList<T> (IEnumerable<T> list) 
{ 
    return new List<T>(list); 
} 

Como otros han mencionado, no estoy seguro de lo útil que es esto. ¿Obtienes intellisense y todo eso cuando lo escribes, por lo que probablemente haya algunos ahorros de tipeo, al menos? :)

+0

¡Heheh! Imitador Podría hacer eso también si tuviera ganas de hacer trampas con Reflector. :-) Pero muchas gracias. –

+0

¡Difícil! ¿Debería el cheque verde venir a ti? Una dificil. Realmente difícil. :-) –

+0

Me alegro por mi primer chequey verde: P De hecho, escribí esto basado en la pregunta (no se utilizó Reflector); Realmente no había pensado en usar tipos anónimos de esta manera. Es un atajo bastante genial, en realidad. – arootbeer

8

El punto era que si nosotros sabíamos de ToList que tendríamos una forma de crear la lista sin tener nuestro propio tipo Film en absoluto. No es que pudiéramos mezclar un tipo anónimo con un tipo Film. En otras palabras, podríamos hacer:

// The type of list will be List<T> where T is the anonymous type 
var list = new[] 
{ 
    new { Name = "North By Northwest", Year = 1959 }, 
    new { Name = "The Green Mile", Year = 1999}, 
    new { Name = "The Pursuit of Happyness", Year = 2006} 
}.ToList(); 

list.ForEach(x => Console.WriteLine("{0} ({1})", x.Name, x.Year)); 

contenta de que estés disfrutando de la primera edición, por cierto - espero que no sea demasiado tiempo antes de la segunda edición sale :)

+0

Todavía estoy ansiosamente esperando esa segunda edición, de la cual regularmente recibo actualizaciones de ... posposición. ¡Pero estoy seguro de que valdrá la pena la espera! – Abel

+0

@Abel: Ooh, no sabía que estaban enviando avisos de aplazamiento :(Si es un consuelo, acabo de recibir los dos primeros capítulos de revisión después de la primera, lo que significa que realmente se está acercando. Estoy tan ansioso por sacarlo como lo está recibiendo, estoy seguro :) –

+0

Hola Jon, entiendo lo que sería la vida si pudiéramos usar el método de extensión ToList(). Solo quiero probar el truco que mencionaste, si ToList() no existía en absoluto.
Quiero algunas líneas nuevas, así que déjame probar algo de XHTML.
PD: Por supuesto, me encanta el libro. Esta es mi segunda lectura. El primero fue una lectura rápida. Este es con probar cada pequeño detalle en el libro. No puedo esperar para la segunda edición. Estoy llevando a cabo una capacitación C# 4 de 54 horas en mi empresa y distribuyendo copias a los ganadores del pop-quiz. :-) –

4

no lo hago piense que lo que Jon está describiendo es realmente muy útil para usted aquí. El único punto que está haciendo es que normalmente no crearía una clase completa Film solo para este ejemplo, si no fuera por los problemas al crear un List<AnonType>.

Edit: Damn. Bien, esta vez estoy dejando mi respuesta aquí de todos modos :)

Cuestiones relacionadas