-1

I have the following method, which works perfectly.

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

But, I want to extend the scope of movieSequence. Since it is of anonymous array type, its type couldn't be pin pointed.

IEnumerable doesn't work since T can't be specified, object in place of T couldn't bring movie.Name, movie.Genre etc.

Non-generic IEnumerable doesn't have Select extension.

IList, ICollection (parents of array) etc. doesn't have Select extension. Obviously "var" is not an option at the class level.

What could be the possible type?

Matt Dawdy
  • 19,247
  • 18
  • 66
  • 91
SaravananArumugam
  • 3,680
  • 6
  • 33
  • 45
  • possible duplicate of [Accessing C# Anonymous Type Objects](http://stackoverflow.com/questions/713521/accessing-c-sharp-anonymous-type-objects) – nawfal Jun 28 '14 at 08:40

5 Answers5

3

This is a bad idea. While it is possible using a combination of IEnumerable<object> and dynamic to extend the scope of an enumeration of an anonymous type this really smells of bad design.

Just create a dedicated class for this that you can pass around in a strongly typed fashion. It will be much easier to read, maintain and refactor later.

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • I agree with you. The code would be hard to maintain with such coding. But just wanted to explore the possibilities of handling this situation. Thank you for the response. – SaravananArumugam Jul 27 '11 at 01:51
3

I think (haven't tried it) you could use dynamic[] + IEnumerable<dynamic> instead of just [] + IEnumerable<object>, but I'll advise against it. Much better to actually build a type for your objects.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Wow! Great. It works with dynamic[]. Well I agree, that in a standard app, its not recommended to use anonymous in the way I have coded. But I just wanted to explore the possibilites / abilities of C# to handle this situation, in my practice code. – SaravananArumugam Jul 27 '11 at 01:49
2

The simplest thing to do is simply to extract a type:

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

And replace new {...} with new Movie{...}. You can leave the array automatically typed.

porges
  • 30,133
  • 4
  • 83
  • 114
1

If you want to refer to an anonymous type outside its scope you should consider converting it to a concrete type. Anonymous types were specifically designed to be tied to a small scope (say, inside a LINQ query).

If you just need access to the object you can either use reflection or the old cast by example trick:

Cast to Anonymous Type

Community
  • 1
  • 1
Ron Warholic
  • 9,994
  • 31
  • 47
1

I think the best option is to make a concrete type out of Movie. You could even move the price behavior into that class. There are tools that will help you extract the type. (I know that Resharper does. For a small simple type like this I would probably enter it quickly myself with auto properties and refactor if needed from there.

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

Your deferred execution method would end up something like this:

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

Another option would be to return an IEnumerable<dynamic>, but I would not pursue that unless you had a real need to treat this type as a dynamic type. In my opinion getting around the scope issues of an anonymous type is not a justified use of dynamic.

jdasilva
  • 616
  • 4
  • 9