可枚举的匿名数组的基本类型

时间:2011-07-27 01:37:28

标签: c# linq ienumerable

我有以下方法,它完美无缺。

//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”不是班级的选择。

可能的类型是什么?

5 个答案:

答案 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查询中)。

如果您只是需要访问该对象,您可以使用反射或旧的按示例演绎:

Cast to Anonymous Type

答案 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>,但除非你真的需要将此类型视为动态类型,否则我不会追求。在我看来,绕过匿名类型的范围问题并不是对动态的合理使用。