#811 – Extension Methods Can Only Access Public Members of Class

When you write an extension method to extend the behavior of an existing class, the code in your extension method has access only to the public members of the class being extended.  Even though the code that you are writing acts as a new instance method on the class, the code within your method has no special access to the members of the class beyond its public members.

Advertisement

#810 – Where Extension Methods Came From

Extension methods were introduced into the C# language as part of version 3.0 of the language, introduced in November of 2007.  C# 3.0 was part of the same release that included version 3.5 of the .NET Framework.

Extension methods are a language mechanism that can be used in a variety of circumstances.  They were included in the language, however, to help support the features of LINQ (Language Integrated Query), which was also introduced in November, 2007, as part of .NET Framework 3.5.

LINQ includes a large number of extension methods that extend the existing System.Collections.Generic.IEnumerable<T> class, which was part of .NET Framework 2.0.  Adding this functionality by way of extension methods allowed LINQ to operate on standard collections, rather than introducing a new LINQ-specific collection class.

810-001

#809 – Extension Method Signatures Shouldn’t Match Class Methods

The idea of writing an extension method is to create a method that can be invoked in the same way as one of the instance methods of a class.  You can’t override an existing instance method using an extension method, but only add new methods.

If you author an extension method that has the exact same signature as an existing instance method in the class, the compiler won’t complain about your new method.  But if you try invoking the method, the original instance method will be called, rather than your extension method.

    static class StringExtensions
    {
        // Will never get called
        public static int CompareTo(this string s1, string s2)
        {
            return 0;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            string s = "Pan Am";
            int n = s.CompareTo("KLM");    // Original CompareTo method called

            Console.ReadLine();
        }
    }

#808 – Adding Parameters to an Extension Method

When you define an extension method, the first parameter of your method represents the instance that you want the method to act upon.  You can, however, add additional parameters.

An extension method that acts on a string, for example, would have string as the first parameter and then, optionally, some other parameters.

        public static string Decorate(this string s, string frontDec, string backDec)
        {
            return frontDec + " " + s + " " + backDec;
        }

When you invoke the method, you pass in these additional parameters.

            // Using the extension method
            string s = "Salk announces polio vaccine";
            string dec = s.Decorate("<<==", "==>>");
            Console.WriteLine(dec);

808-002

Notice that Intellisense now lists the new extension method as an option for the string type and correctly lists two parameters.
808-001

#807 – Defining and Using an Extension Method

An extension method is a method that you define to extend an existing class without having to modify or inherit from the existing class.  The new method behaves as if it was defined as an instance method of the original class.

For example, you might define a Decorate() method that extends the System.String class.

To define an extension method:

  • Define it in a static class, as a static function
  • The 1st parameter must be of the type that you are extending and must include the this keyword on the parameter
    static class StringExtensions
    {
        public static string Decorate(this string s)
        {
            return "** " + s + " **";
        }
    }

You can now use the extension method as if it was an instance method on the System.String class.

            string s = "Fire at the triangle factory";
            Console.WriteLine(s.Decorate());

807-001

#806 – An Example of Mandatory Use of the var Keyword

When assigning the result of a query expression to a variable, there are cases when you do know the result type and so the use of the var keyword is optional.

However, in some cases, an anonymous type is created to contain the results of the expression.  In these cases, you must use the var keyword, because the correct type is generated internally by the compiler and not available to your code.

In the example below, we get something back that we can iterate on, but each element within the result set is anonymously typed, an object containing Name and Age fields.

            var oldDogs = from aDog in dogs
                                          where aDog.Age > 10
                                          select new { aDog.Name, aDog.Age };

            foreach (var anOldie in oldDogs)
                Console.WriteLine(string.Format("{0}, age {1}", anOldie.Name, anOldie.Age));

#805 – An Example of Discretionary Use of the var Keyword

Below is one example where you may or may not want to use the var keyword.

            var oldDogs = from aDog in dogs
                          where aDog.Age > 10
                          select aDog.Name;

            foreach (var next in oldDogs)
                Console.WriteLine(next);

This works just fine.  We don’t specify the type of the value returned from the query expression, but we know that it’s something that we can iterate on, so we just use var for the result and then var again in the foreach.

The difficulty comes when someone else is going to modify this code.  The query actually returns an enumerable list of strings.  But reading the code, you might make the mistake of thinking that it returns a list of dogs.

We could have been more clear by writing:

            IEnumerable<string> oldDogs = from aDog in dogs
                          where aDog.Age > 10
                          select aDog.Name;

            foreach (string name in oldDogs)
                Console.WriteLine(name);

#804 – Tradeoffs when Using the var Keyword

You’d most often use the var keyword, indicating an implicit type, in the following situations:

  • For anonymous types  (var is required)
  • As the type of the result of a LINQ expression
  • To avoid duplicating a long type name

You should end up using var if its use is required (for anonymous types) or if using var improves the readability of your code.

You must be careful, however, in using var to simplify your code.  In many cases, while its use may make writing your code easier, the omission of a type can make the code less readable, because the person later reading the code may need to first determine the variable’s type before being able to use it.

A good rule of thumb is to use strongly typed variables by default and only use var when it is necessary.

#803 – Situations When You Might Use the var Keyword

The var keyword allows you to avoid entering the full type of a variable, letting the compiler infer the type.  The variable is still strongly-typed, i.e. the type is known at compile time.

There is debate about when you should use var.  It’s use ends up dictated by coding style guidelines or personal preference.

You must use var when dealing with anonymous types because the compiler generates only an internal type name.

var myDog = new { Name = "Kirby", Age = 14 };

You might  use var when using LINQ, when the exact type of the query result is not apparent.

            var someDogs = from aDog in dogs
                          where aDog.Age > 10
                          select aDog.Name + "(" + aDog.Nickname + ")";

You might also use var to avoid having to repeat a type name that is already present in an expression.

            var dogs = new List<Dog>();

#802 – A Method Might Have No Parameters

You can pass one or more data values to a method using parameters.  A parameter in a method is just a variable, usable only within that method, that refers to a piece of data passed into the method.

If the method that you are writing requires no data to be passed in, you can omit all parameters.  You include an empty pair of parentheses after the method name, to indicate that the method has no parameters.

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        // All data that we need is passed into constructor
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        // Bark is a method that has no parameters
        public void Bark()
        {
            Console.WriteLine(string.Format("{0} : WOOF !", Name));
        }
    }