2010-07-15 4 views
9

От Джона Скита замечательной книги C# в глубине, первое издание:Играя с анонимными типами

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); 

Абзац следует выше перечисленному фрагменту кода.

Первая половина листинга 9.4 включает в себя просто настройку данных. Я бы использовал анонимный тип, но довольно сложно создать общий список из коллекции экземпляров анонимного типа. (Вы можете сделать это с помощью , создавая общий метод, который принимает массив и преобразует его в список того же типа, а затем передаёт неявно типизированный массив в этот метод . Метод расширения в .NET 3.5, называемый ToList, предоставляет это функциональность тоже, но это было бы мошенничать, как мы не смотрели на методы расширения еще!)

И фрагмент кода указанного выше, является листинг 9.4 книги, что этот пункт относится.

Мой вопрос: Я опробовать методику, описанную в предыдущем абзаце вручную (смотрите на курсиве), но я не совсем понимаю, что он имел в виду.

Я пытался что-то вроде этого, но это не то, что он имел в виду, я полагаю, что это не работает (и я не ожидал, что это к):

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; 

    } 
} 

}

Примечание: Я знаю об методе расширения IEnumerable.ToList() и использовал его много раз. Я просто хочу попробовать технику, изложенную в параграфе вручную.

Кроме того, я заинтригован сценариями, в которых анонимные типы используются вне Linq, поскольку синтаксическое удобство и один из таких сценариев приведен ниже. Я всегда могу использовать dynamic в C# 4 и принимать анонимный тип в качестве аргумента и работать с ним, зная, чего я ожидаю. Я хотел бы сделать это с помощью C# 3. Что-то, как показано ниже:

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 
     } 
    } 
} 

}

Edit Они должны иметь бирку с именем джон-тарелочкам.

+1

Я знаю, кто выиграет этот вопрос;) – Skurmedel

+0

Было бы очень иронично, если бы задали вопрос о книге Джона, Джон был ответом и кто-то другой выиграл lol – Icemanind

+0

@Skurmedel Он он! –

ответ

6

Чтобы на самом деле сделать это:

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); 
} 

Как уже упоминалось, я не уверен, как это полезно. Вы получаете intellisense и все это, когда вы пишете его, так что, вероятно, есть некоторые сбережения для ввода, по крайней мере? :)

+0

Хе-хе! Copycat. Я тоже мог бы это сделать, если бы мне захотелось обмануть Рефлектора. :-) Но большое спасибо. –

+0

Жесткий! Должен ли зеленый чек быть к вам? Крепкий орешек. Настоящий жесткий. :-) –

+0

Радость за мою первую зеленую проверку: P Я на самом деле написал это на основе вопроса (нет рефлектора); Я не думал об использовании анонимных типов. На самом деле это довольно крутой ярлык. – arootbeer

8

Дело было в том, что если бы мы знали о ToList, у нас был бы способ создать список, не имея собственного типа Film. Дело не в том, что мы могли бы смешивать анонимный тип с типом Film. Другими словами, мы могли бы сделать:

// 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)); 

Рад, что вы будете наслаждаться первое издание, кстати - мы надеемся, это не будет слишком долго, прежде чем второе издание выходит :)

+0

С нетерпением жду этого 2-го издания, из которого я регулярно получаю обновления ... откладывания. Но я уверен, что это будет стоить ждать! – Abel

+0

@ Абель: Ой, я не знал, что они отправляют уведомления о переносе :(Если это утешение, я только что получил первые два столбца после первого исправления, что означает, что он действительно приближается. как я хочу, чтобы получить его, как вы его получите, я уверен :) –

+0

Привет, Джон, я понимаю, какой будет жизнь, если мы сможем использовать метод расширения ToList(). Я просто хочу попробовать хак, о котором вы говорили, если ToList() вообще не существует.
Я хочу несколько новых линий, поэтому позвольте мне попробовать некоторые XHTML.
PS: Конечно, я люблю книгу. Это мое второе чтение. Первое - быстрое чтение. Это один из них, в каждой из которых подробно описывается каждая книга. Я просто не могу дождаться второго издания. Я провожу 54-часовой курс C# 4 в своей компании и раздаю копии победителям поп-викторины. :-) –

4

Я не думаю, что Джона описывает, на самом деле очень полезно для вас здесь. Единственное, что он делает, это то, что он обычно не создавал целый класс Film только для этого примера, если бы не проблемы с созданием List<AnonType>.

Редактировать: Черт. Хорошо, на этот раз я оставляю мой ответ здесь в любом случае :)

Смежные вопросы