繁体   English   中英

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

[英]Base type of Anonymous Array that is Enumerable

我有以下方法,效果很好。

//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 的对象无法带来电影名称、电影类型等。

非通用 IEnumerable 没有 Select 扩展名。

IList、ICollection(数组的父级)等没有 S​​elect 扩展名。 显然“var”不是类级别的选项。

可能的类型是什么?

这是一个坏主意。 虽然可以使用IEnumerable<object>dynamic的组合来扩展匿名类型的枚举范围,但这确实是一种糟糕的设计。

只需为此创建一个专用类,您就可以以强类型方式传递它。 以后阅读、维护和重构会容易得多。

我认为(还没有尝试过)你可以使用dynamic[] + IEnumerable<dynamic>而不是[] + IEnumerable<object> ,但我会建议不要这样做。 为您的对象实际构建一个类型要好得多。

最简单的事情就是简单地提取一个类型:

class Movie 
{
   string Name {get;set;}
   string Genre {get;set;}
   int ReleasedYear {get;set;}
   decimal Price {get;set;}
}

并将new {...}替换为new Movie{...} 您可以保留自动键入的数组。

如果要引用其范围之外的匿名类型,则应考虑将其转换为具体类型。 匿名类型专门设计为绑定到一个小范围(例如,在 LINQ 查询中)。

如果您只需要访问对象,您可以使用反射或旧的示例技巧:

转换为匿名类型

我认为最好的选择是用 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> ,但除非您确实需要将此类型视为动态类型,否则我不会这样做。 在我看来,绕过匿名类型的范围问题并不是动态的合理使用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM