Из замечательной книги Джона Скита C # In Depth, First Edition :
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 У них должен быть тег с именем jon-skeet.