#651 – Passing an Anonymously-Typed Object to a Method

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

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

You normally can’t pass this object to a method because there is no explicit type for the object and you cannot define an implicitly-typed parameter for a method.

However, you can use a dynamically-typed parameter (dynamic keyword) to pass the anonymously-typed object to a method.

    public static class MovieUtility
    {
        public static void DumpFromAnonType(dynamic anonType)
        {
            Console.WriteLine("Title = {0}", anonType.Title);
        }
    }

 

            var movie = new { Title = "North By Northwest", Year = 1959, Director = "Alfred Hitchcock" };
            MovieUtility.DumpFromAnonType(movie);

This code will compile and will execute properly if run. Passing an object that doesn’t have a Title property to the method will result in a run-time error.

#650 – Creating an Array of Anonymously-Typed Objects

An anonymous type is a temporary data type that is inferred based on the data that you include in an object initializer.  In addition to creating a single anonymously-typed object with an object initializer, you can also create an array of 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" }};

With this declaration, you end up with an array of anonymously-typed objects, each of which has the properties Title, Year, and Direction.

Note that this implicitly-typed array must contain elements of the same type, so each element must have the exact  same set of properties.

#649 – Creating an Anonymous Type

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

We can use object initializer syntax to initialize an object:

Dog kirby = new Dog { Name="Kirby", Age=14 };

We can use the same syntax to initialize an object where we don’t mention a particular data type.  For example, we can declare/initialize an object that contains some information about a movie.

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

Notice that we haven’t created a Movie class, but we now have an object that represents a movie which has three properties–Title, Year and Director.

The compiler has actually created a temporary “anonymous” type to represent the movie object.  Note also that the movie variable is implicitly typed (var keyword)since we don’t have a named type.

#648 – Using an Object Initializer

You typically initialize the data members of an object by invoking one of the object’s constructors and passing it any information that it requires.  For example:

Dog kirby = new Dog("Kirby", 14);

If a parameterless constructor exists for the class, you can alternatively create the object without invoking a constructor, using the object initializer syntax shown below.

Dog kirby = new Dog { Name="Kirby", Age=14 };

This is functionally equivalent to:

Dog kirby = new Dog();
kirby.Name = "Kirby";
kirby.Age = 14;

If a parameterless constructor does not exist for the class, you can still use the object initializer syntax, but only after explicitly invoking one of the constructors.

#647 – A struct Can Implement an Interface

You’ll most often see an interface implemented by a class, but a struct can also implement an interface.

struct implements an interface in the same way as a class–by listing the name of the interface after the name of the struct and then by providing implementations of the members in the interface.

Suppose that we had the following interface:

    public interface IBoxCalcs
    {
        double CalcVolume();
        double CalcSurfaceArea();
    }

We can then implement this interface in a struct.

    public struct BoxSize : IBoxCalcs
    {
        public double x;
        public double y;
        public double z;

        // Constructor that fully initializes the object
        public BoxSize(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public double CalcVolume()
        {
            return x * y * z;
        }

        public double CalcSurfaceArea()
        {
            return (2 * x * y) + (2 * x * z) + (2 * y * z);
        }
    }

#646 – Value Types Don’t Have Finalizers

In .NET, you override the Object.Finalize method to dispose of any unmanaged resources when the object is being garbage collected.  In C#, you write this finalizer using the destructor (~) syntax.  You can also implement the Dispose pattern to allow users of your object to deterministically dispose of  resources.

You cannot implement a finalizer or the dispose pattern for a value type.  A finalizer makes no sense for a value type because value typed objects are not garbage collected–they simply die when they go out of scope.

Since the finalizer and the dispose pattern exist for the purpose of releasing unmanaged resources, and you can’t implement either for a value type, you should avoid using unmanaged resources in value types.  A user would have to explicitly call some method to do the cleanup and there is no guarantee that they would remember to call the method.

#645 – You Can Chain to the Default Constructor for a struct

You can use the this keyword in a constructor within a struct to invoke other constructors (constructor chaining).

public BoxSize(double x, double y)
    : this(x, y, 1.0)
    {
    }

Every struct also has a default parameterless constructor that you can explicitly invoke when creating an object of the struct’s type.

            BoxSize bs = new BoxSize();

Additionally, you can use the this keyword to chain to this default constructor from another constructor.  Doing so results in all fields being assigned to default values.

        // Initialize x and y to specified values,
        //   initialize z to default value.
        public BoxSize(double x, double y)
            : this()
        {
            this.x = x;
            this.y = y;
        }

#644 – Chaining struct Constructors

In the same way that one constructor for a class can call another, a constructor for a struct can call another constructor, using the this keyword.  In this way, one constructor for the struct calls another, to help initialize the data in the struct.

In the example below, we define two constructors for the BoxSize struct.  The constructor that takes only two parameters chains to the three-parameter constructor, using the this keyword.

    public struct BoxSize
    {
        public double x;
        public double y;
        public double z;

        // Constructor that fully initializes the object
        public BoxSize(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        // 2nd constructor that allows user to specify
        //   only X & Y and we then default Z to 1.0
        public BoxSize(double x, double y)
            : this(x, y, 1.0)
        {
        }

        public void PrintBoxSize()
        {
            Console.WriteLine(string.Format("X={0}, Y={1}, Z={2}", x, y, z));
        }
    }

#643 – The Constructor for a struct Must Initialize All Data Members

.NET requires that you initialize all memory for an object before you use it.  When it comes to a struct, this means that you must do one of three things when declaring a new instance of a struct:

  • Invoke the default parameterless constructor, which initializes all elements within the struct.  (E.g. zeroes out simple value types)
  • Declare the new instance and then set data members explicitly (assuming that they are all public)
  • Invoke a custom constructor, which initializes all data members

This means that if you define a non-default constructor for a struct, your constructor must initialize all data members in the struct before it returns. to the caller.  This guarantees that any creation of a struct-based value type will result in an object which is safe to use, because all of its data members have known values.

#642 – Reassigning the this Pointer in a struct

The this keyword in a struct refers to the current instance of the object represented by the struct.  

You can actually assign a new value to the this keyword, provided that the new value is an instance of the same struct.

    public struct BoxSize
    {
        public double x;
        public double y;
        public double z;

        public BoxSize(double x, double y, double z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }

        public void CopyFrom(BoxSize newBoxSize)
        {
            // Overwrite existing BoxSize with a new one
            //   by assigning new value to this keyword
            this = newBoxSize;
        }

        public void PrintBoxSize()
        {
            Console.WriteLine(string.Format("X={0}, Y={1}, Z={2}", x, y, z));
        }
    }
        static void Main()
        {
            BoxSize myBox = new BoxSize(5, 2, 3);
            myBox.PrintBoxSize();

            myBox.CopyFrom(new BoxSize(10, 20, 30));
            myBox.PrintBoxSize();
        }