#840 – Use an Anonymous Type as a Read-Only Subset of an Object

You often use anonymous types to store some subset of data from another object.  In many cases, you’re interested in only a subset of the properties present in the original object.  With an anonymous type, you get a new object containing only the properties that you care about.

In the example below, the dogInfo object declaration creates an anonymous type containing only two of the properties present in the Dog object that it is referring to.  These properties, as they exist in the new object, are read-only.

            Dog myDog = new Dog("Kirby", 15, "Balls balls balls", "Tennis ball",
                42.0, "Black");

            var dogInfo = new { myDog.Name, myDog.Age };

840-001

Advertisements

#839 – Anonymous Type Limitations

An anonymous type is a temporary data type that is inferred based on the data that you include in an object initializer.

An anonymous type has a couple of  limitations.  Its only members are public, read-only properties.  The type can’t contain methods or other type members and you cannot write to its properties.

            var tt = new { Name = "Kirby", Age = 12 };
            tt.Name = "bob";   // Error - Name can't be assigned to

The anonymous type must be implicitly convertible to the type of a variable used to store the new object.  In other words, the variable must either be implicitly typed using the var keyword, or must be of type object.  You’ll almost always want to use the first option, since the resulting variable is still strongly typed.

#833 – Some Examples of Anonymous Object Initializers

You create an anonymously-typed object using the object initializer syntax.  The declaration consists of a series of member declarators, each of which can be:

  • A named value (Name = value)
  • A value represented by a named object
            Dog myDog = new Dog("Kirby", 15);
            Dog otherDog = new Dog("Ruby", 3);

            var anon1 = new {Name = "Bob", Age = 49};
            var anon2 = new {DogName = myDog.Name, DogAge = myDog.Age};
            var anon3 = new {Name = "Pi", Value = Math.PI};
            var anon4 = new { Area = CalculateArea(2.0, 3.0) };
            int num = 42;
            var anon5 = new { FavoriteNumber = num, Name = "Arthur" };
            var anon6 = new { Dog = myDog, Owner = new Person("Billy") };
            var anon7 = new { FavNum = anon5, SomeGuy = anon1 };

            var anon8 = new {myDog.Name, myDog.Age};
            var anon9 = new { Math.PI, Math.E };
            string name = "Nelson";
            var anon10 = new { num, name };
            var anon11 = new { myDog, otherDog };
            var anonGroup = new { anon1, anon2, anon3 };

            var anon12 = new { Dog1 = myDog, name };

#775 – Copying an Array of Anonymously-Typed Objects

You can create an implicitly-typed array that contains an array of anonymously-typed objects.

            var movies = new[] {
                new { Title = "North By Northwest", Year = 1959, Director = "Alfred Hitchcock" },
                new { Title = "Zelig", Year = 1983, Director = "Woody Allen" },
                new { Title = "King Kong", Year = 2005, Director = "Peter Jackson" }};

If you’d like to create a copy of this array, you can use the Clone method.  This will create a new array of the same type and copy all of the anonymously-typed elements to the new array.

            var copy = movies.Clone();

#654 – You Can’t Use an Anonymous Type Directly

An anonymous type is a temporary data type that is inferred based on the data that you include in an object initializer.  For example, the code below causes a class to be generated that contains three properties–Title, Year and Director.

var movie = new { Title = "Gladiator", Year=2000, Director = "Ridley Scott" };

When you declare an object with an anonymous type like this, the compiler automatically generates the type for you.  You can use ILDASM to look at the IL for this code and see the type.  It has a fairly cryptic name.

While the compiler creates a type to represent the object that you declared, you can’t reference this type explicitly in your code.

#653 – Projection Initializers

A projection initializer is a declaration for a member of an anonymous type that does not include a property name.

Here’s an example, where the members of the anonymous type are initialized using local variables.  The resulting property names in the anonymously-typed object match the variable names.

string title = "Seven Samurai";
string director = "Akira Kurosawa";
int year = 1956;

var movie = new { title, year, director };


You can also use properties of another object to initialize the anonymously-typed objects members.

            MovieInfo mi = new MovieInfo("Seven Samurai", "Akira Kurosawa", 1956);

            var movie = new { mi.Title, mi.Year, mi.Director };

#652 – Using Expressions and Variables in Anonymous Type Declarations

One way to declare an anonymous type is to specify the name of each property of the new type, along with the value of that property, expressed as a constant.

var movie = new { Title = "North By Northwest", Year = 1959, Director = "Alfred Hitchcock" };

When you declare an anonymously-typed object, you can use any expression as the value for a property.

// Note: GetFavMovie() returns a string
int birthYear = 1964;
var movie2 = new { Title = GetFavMovie(), Year = birthYear - 25, Director = movie.Director };

You can also leave off the named property and just include an named identifier representing a value.

        public static string Director { get; set; }
        private const int TheYear = 1956;

        static void Main()
        {
            string aMovieTitle = "Seven Samurai";
            Program.Director = "Akira Kurosawa";

            var movie2 = new { aMovieTitle, TheYear, Program.Director };
        }

The property names in the generated type will match the identifiers that you use.