Wednesday, December 19, 2007

Anonymous types sharing or why it's still sucks?

Did you try to cast anonymous types (vars)? You are. However, you never was able to pass var from one method to another. Why is it? Cos, anonymous type got known in context of current method only. Well, we always can cast one anonymous type into other. How? By using Extension methods. Let's make small repro. In one method, you have following structure

var myVar = new[] {
               new {Name = "Pit", Kind = "Alien},
               new {Name = "John", Kind = "Predator"},
               new {Name = "Fred", Kind = "Human"}
           };

In other method, you have other variable

var theirVar = new[] {
                new {Name = "Kent", Kind = "Alien"},
                new {Name = "Rob", Kind = "Predator"},
                new {Name = "Bill", Kind = "Human"}
            };

Cool. Now you can cast myVar easily into object or object array, and transfer it into other method. Then, cast theirVar into another object or object array and cast myVar into theirVar, right? Why not to use extension to make your live easier (tnx to AlexJ)?

public static class Extender
   {
       public static T Cast<T>(this object obj, T what)
       {
           return (T)obj;
       }
   }

Now, it's very cool part. Change theirVar assignment to following:

var theirVar = myVar.Cast(new[] {
               new {Name = "Kent", Kind = "Alien"},
               new {Name = "Rob", Kind = "Predator"},
               new {Name = "Bill", Kind = "Human"}
           });

You got theirVar type of myVar type. Isn't it cool? You even can enumerate through those objects, by using strong types

foreach (var q in theirVar)
            {
                Console.WriteLine("{0}-{1}", q.Name, q.Kind);
            }

Well, as always, I have a goat for you. Let's change myType as following

var myVar = new[] {
               new {Name = "Pit", Kind = "Alien", Goat = "bee"},
               new {Name = "John", Kind = "Predator", Goat = "mee"},
               new {Name = "Fred", Kind = "Human", Goat = "eee"}
           };

And we will not tell to theirType developer about what type Goat member is. So, we let him write

var theirVar = myVar.Cast(new[] {
                new {Name = "Kent", Kind = "Alien", Goat = 1},
                new {Name = "Rob", Kind = "Predator", Goat = 2},
                new {Name = "Bill", Kind = "Human", Goat = 3}
            });

Eaht! Will it works? Sure, if exceptions will be handled. Actually, you'll get

Unable to cast object of type '<>f__AnonymousType0`3[System.String,System.String,System.String][]' to type '<>f__AnonymousType0`3[System.String,System.String,System.Int32][]'.

Extremely informative exception (if you know what <>f__AnonymousType0 is). Isn't it? Don't use anonymous types. It's bad behavior! Have a nice day and be good people.

No comments: