#549 – Anonymous Method Basics

Recall that an instance of a delegate is an object that refers to one or more methods.  Code that has access to the delegate  instance can execute the various methods via the delegate.

        private delegate void StringHandlerDelegate(string s);

        static void Main()
        {
            StringHandlerDelegate del1 = Method1;
            del1("Invoked via delegate");
        }

        static void Method1(string text)
        {
            Console.WriteLine(text);
        }

An anonymous method is a shorthand for declaring a delegate instance that allows declaring the code to execute as part of the delegate’s declaration, rather than in a separate method.

The code below is equivalent to the example above, but using an anonymous method, rather than a separately defined method.

        private delegate void StringHandlerDelegate(string s);

        static void Main()
        {
            StringHandlerDelegate del1 =
                delegate (string s) { Console.WriteLine(s); };
            del1("Invoked via delegate");
        }

#541 – Generic Method Type Parameters Can Hide Class-Level Type Parameters

When you have generic methods within a generic class, if the name of a type parameter in the generic method matches the name of a type parameter for the class, the parameter in the method takes precedence.

In the example below, both the Dog class and the BuryThing method declare a type parameter named T.  Within the body of the BuryThing method, the method’s type parameter is used, rather than the class-level type parameter of the same name.

    public class Dog<T>
    {
        // This method's type parameter hides the class-level type parameter
        public void BuryThing<T>(T thing)
        {
            Console.WriteLine("T's type is {0}", typeof(T).ToString());
        }

 

            Dog<Cow> d = new Dog<Cow>("Buster", 5);
            d.BuryThing(new Bone("Rawhide"));

To avoid this confusion, you should give your type parameters meaningful names, e.g. TDogThing and TThingToBury.

#540 – Non-Generic Methods in a Generic Class

You can have both generic and non-generic methods in a generic class.  The non-generic methods can still make use of the class’ generic type parameters.

In the example below, the BuryThing method accepts a parameter whose type matches the type parameter of the class itself.

    public class Dog<T>
    {
        // Generic method can access type parameter of class
        public void BuryThing(T thing)
        {
            Console.WriteLine(string.Format("{0} is burying: {1}", Name, thing.ToString()));
        }

When we invoke this method, we must pass it an object whose type matches the type parameter that the class was constructed with.

            Dog<Cow> d = new Dog<Cow>("Buster", 5);
            d.BuryThing(new Cow("Bessie"));

#539 – Type Inference When Calling Generic Methods

When you call a generic method, you can provide a type argument, indicating the type for any type parameters, or you can let the type be inferred by the compiler.

For the following type definition:

public static void DogBuriesThing<T>(Dog d, T thing)

You can either provide the type argument:

            Dog buster = new Dog("Buster", 5);
            Dog.DogBuriesThing<Bone>(buster, new Bone("Buster's rawhide"));

Or you can omit the type when you call the method, letting the type be inferred based on the type of the second argument:

            Dog.DogBuriesThing(buster, new Cow("Bessie"));

#538 – Implement a Generic Method

In addition to classes, structs and interfaces, a method can also be generic.  A generic method is one that is declared with type parameters.  A generic method can be either a static method or an instance method.

In the example below, notice that both methods are generic, though the Dog class itself is not generic.

    public class Dog
    {
        // Generic static method
        public static void DogBuriesThing<T>(Dog d, T thing)
        {
            Console.WriteLine(string.Format("{0} is burying: {1}", d.Name, thing.ToString()));
        }

        // Generic instance method
        public void BuryThing<T>(T thing)
        {
            Console.WriteLine(string.Format("{0} is burying: {1}", Name, thing.ToString()));
        }

Examples of calling these methods:

            // Call generic static method
            Dog buster = new Dog("Buster", 5);
            Dog.DogBuriesThing<Bone>(buster, new Bone("Buster's rawhide"));

            // Call generic instance method
            buster.BuryThing<Cow>(new Cow("Bessie"));

#513 – Some Familiar Methods that Accept Parameter Arrays

There are a number of methods in classes in the .NET Framework that accept parameter arrays, allowing you to pass a variable number of arguments to them.  Here are some examples:

String.Format:

int ft = 5;
int inches = 2;
string eyeColor = "blue";
string exclamation = "oh";
// string string.Format(string format, params object[] args)
string lyric = string.Format("{0} ft {1}, eyes of {2}; but {3} what those {0} foot could do", ft, inches, eyeColor, exclamation);

Console.WriteLine:

            string[] favs = {"Kittens", "Mittens", "Packages", "Tractors", "Streudel"};
            // void Console.WriteLine(string format, params object[] args)
            Console.WriteLine("Fav things: {0}, {1}, {2}, {3}, {4}", favs);

(Note: Console.WriteLine has an overload that accepts four object parameters after the format string, so the version with the parameter array doesn’t kick in until you use at least five parameters).

Path.Combine:

// string Path.Combine(params string[] paths)
string path = Path.Combine("D:\\", "Sean", "Notes", "WCF");

#512 – Two Ways to Pass Data to a Method that Takes a Parameter Array

Defining a parameter array using the params keyword allows you to pass a variable number of arguments to a method.

public void PerformCommands(params string[] commands)

You can pass a variable number of arguments to a method that has a parameter array.

            kirby.PerformCommands("Sit", "Stay", "Beg");

You can also just pass an array of the proper type.

            string[] tricks = new string[] {"Roll over", "Weave"};

            kirby.PerformCommands(tricks);

#511 – Rules for Using Parameter Arrays

You can use the params keyword when declaring a method to define a parameter array, allowing you to pass a variable number of parameters to the method.

public void PerformCommands(params string[] commandList)
{
    foreach (string command in commandList)
        Console.WriteLine("Ok, I'm doing [{0}]", command);
}

You can then pass any number of parameters to the method.  Every parameter that you specify is added to the single array that is passed to the method.

kirby.PerformCommands(new string[] { "Sit", "Stay", "Come" });

When using the params keyword:

  • You can only define one parameter array for a given method
  • The parameter must be the last parameter specified
  • The array must be a single-dimensional array
  • You can’t use the ref or out modifiers on the parameter array or on any of the arguments
  • Each argument must be implicitly convertible to the type of the array’s elements

#354 – Correct Overloaded Method Is Automatically Called

When you have several overloaded methods in a class, the compiler will call the correct method, based on the type of the arguments passed to the method.

When you overload a method, you define several methods in a class with the same name, but different parameters.

    public class Dog
    {
        // General bark
        public void Bark()
        {
            Console.WriteLine("Woof");
        }

        // Specific bark
        public void Bark(string barkSound)
        {
            Console.WriteLine(barkSound);
        }

        // Repeated barking
        public void Bark(int numBarks)
        {
            for (int i = 1; i <= numBarks; i++)
                Console.WriteLine("Woof #{0}", i);
        }
    }

The compiler will automatically figure out which method to call, based on the arguments that you pass in.

            Dog jack = new Dog("Jack", 15);

            jack.Bark();           // General bark
            jack.Bark(5);          // Repeated barking
            jack.Bark("Rowwwwf");  // Specific bark

#341 – Defining and Using Local Variables

You can define variables within a method.  These are known as local variables.  The variables’ values can be read and written while the body of the method is executing.

The Dog.Bark method below defines two local variables–formalName and barkPhrase.

    public class Dog
    {
        public string Name { get; set; }
        public string BarkSound { get; set; }

        public void Bark()
        {
            string formalName = string.Format("Sir {0}", Name);
            string barkPhrase = string.Format("{0} {0}!", BarkSound);

            Console.WriteLine("{0} says {1}", formalName, barkPhrase);
        }
    }

Local variables can be initialized when they are declared, or they can be set to a value later.  Since C# requires definite assignment, they must be given a value before they are read.

 

Follow

Get every new post delivered to your Inbox.

Join 43 other followers