我有以下方法,它完美无缺。
//private static IEnumerable<object> movieSequence;
private static void DeferredExecution()
{
var movieSequence = new[] {
new {Name="Harry potter", Genre="Action/Thrill", ReleasedYear=2011, Price=24.0},
new {Name="Tooth fairy", Genre="Family", ReleasedYear=2010, Price=20.5},
new {Name="How to train your dragon", Genre="Family", ReleasedYear=2010, Price=20.5}
};
double priceMultiplier = 0.5;
var newPriceList = movieSequence.Select(movie => new
{
Name = movie.Name,
Genre = movie.Genre,
ReleasedDate = movie.ReleasedYear,
Price = movie.Price * priceMultiplier
});
foreach (var movie in newPriceList)
{
Console.WriteLine("{0} ({1}) costs ${2}", movie.Name, movie.ReleasedDate, movie.Price);
}
}
但是,我想扩展movieSequence的范围。由于它是匿名数组类型,因此其类型不能用针对指针。
IEnumerable不起作用,因为无法指定T,代替T的对象无法带来movie.Name,movie.Genre等。
非通用IEnumerable没有选择扩展名。
IList,ICollection(数组父项)等没有Select扩展名。显然,“var”不是班级的选择。
可能的类型是什么?
答案 0 :(得分:3)
这是一个坏主意。虽然可以使用IEnumerable<object>
和dynamic
的组合来扩展匿名类型的枚举范围,但这确实有点糟糕的设计。
只需为此创建一个专用类,您就可以以强类型方式传递它。稍后阅读,维护和重构会更容易。
答案 1 :(得分:3)
我认为(还没有尝试过)你可以使用dynamic[]
+ IEnumerable<dynamic>
而不只是[]
+ IEnumerable<object>
,但我会反对它。实际为您的对象构建类型要好得多。
答案 2 :(得分:2)
最简单的方法就是提取一个类型:
class Movie
{
string Name {get;set;}
string Genre {get;set;}
int ReleasedYear {get;set;}
decimal Price {get;set;}
}
将new {...}
替换为new Movie{...}
。您可以自动键入数组。
答案 3 :(得分:1)
如果要引用其范围之外的匿名类型,则应考虑将其转换为具体类型。匿名类型专门设计为绑定到一个小范围(例如,在LINQ查询中)。
如果您只是需要访问该对象,您可以使用反射或旧的按示例演绎:
答案 4 :(得分:1)
我认为最好的选择是用Movie制作一个具体的类型。您甚至可以将价格行为转移到该类中。有些工具可以帮助您提取类型。 (我知道Resharper会这样做。对于像这样的小型简单类型,如果需要的话,我可能会自动输入自动属性和重构。
public class Movie
{
public string Name { get; set; }
public string Genre { get; set; }
public int ReleasedYear { get; set; }
public double Price { get; set; }
public Movie ChangePrice( double multiplier )
{
return new Movie()
{
Name = Name,
Genre = Genre,
ReleasedYear = ReleasedYear,
Price = Price * multiplier
};
}
}
您的延迟执行方法最终会是这样的:
static IEnumerable<Movie> NewPriceList()
{
var movieSequence = new[]
{
new Movie("Harry potter", "Action/Thrill", 2011, 24.0),
new Movie("Tooth fairy", "Family", 2010, 20.5),
new Movie("How to train your dragon", "Family", 2010, 20.5)
};
double priceMultiplier = 0.5;
return movieSequence.Select(movie => movie.ChangePrice(priceMultiplier));
}
另一个选择是返回IEnumerable<dynamic>
,但除非你真的需要将此类型视为动态类型,否则我不会追求。在我看来,绕过匿名类型的范围问题并不是对动态的合理使用。