#1,136 – Overloading a Generic Method

In the same way that you can overload a generic class, you can overload a generic method, defining multiple generic methods having the same name but different type parameters.  You can also define non-generic methods with the same name.

Below, we overload the Dog.Bury method, defining several non-generic and several generic methods.

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

        public Dog(string name)
        {
            Name = name;
        }

        public void Bury(Bone b)
        {
            Console.WriteLine("{0} is burying: {1}", Name, b);
        }

        public void Bury(Lawyer l)
        {
            Console.WriteLine("{0} is burying: {1}", Name, l);
        }

        public void Bury<T>(T thing)
        {
            Console.WriteLine("{0} is burying: {1}", Name, thing);
        }

        public void Bury<T>(T thing, string msg)
        {
            Console.WriteLine("{0} : {1}", msg, thing);
        }

        public void Bury<T1, T2>(T1 thing1, T2 thing2)
        {
            Console.WriteLine("{0} is burying: {1}", Name, thing1);
            Console.WriteLine("{0} is burying: {1}", Name, thing2);
        }
    }

We can call these methods as follows:

            Dog fido = new Dog("Fido");

            fido.Bury(new Bone());
            fido.Bury(new Lawyer());
            fido.Bury<Cow>(new Cow("Bessie"));
            fido.Bury<Lawyer>(new Lawyer(), "One less lawyer");
            fido.Bury<Cow,Cat>(new Cow("Bessie"), new Cat("Puffy"));
Advertisement

#674 – Can Overload If Parameters Differ Only by ref Modifier

You can overload methods, i.e. create two methods with the same name, if the methods have different parameter lists, where the lists differ in the number or type of the parameters.  For example:

        public void Fetch(Bone b)
        {
            Console.WriteLine(string.Format("Fetching bone {0}", b.Description));
        }

        public void Fetch(Dog d)
        {
            Console.WriteLine(string.Format("I'll go get {0}", d.Name));
        }

You can also overload methods if they differ only in their use of the ref modifier.  One method can accept a parameter passed by value and you can have another version of the method that allows passing the parameter by reference.

        public void Bark(string sound)
        {
            Console.WriteLine(sound);
        }

        public void Bark(ref string sound)
        {
            Console.WriteLine(sound);

            // Update caller's copy of sound variable
            sound = sound + "!";
        }
            Dog d = new Dog("Rex", 3);
            string sound = "woof";
            d.Bark(sound);
            d.Bark(ref sound);   // woof!
            d.Bark(ref sound);   // woof!!

#595 – Intellisense Shows Method Overloads

When you overload a method, you’re creating multiple methods with the same name, but a different number of parameters, or parameters of different types.  At compile-time, the compiler will automatically call the correct method.

Visual Studio can help with entering parameter values.  When you enter the name of a method, Intellisense shows you a list of available methods with that name.

Let’s say that we have three different versions of a Dog.Bark method.  After typing “Bark” and the opening parenthesis “(“, Intellisense will indicate that there are three versions of the method available and provide information about the first version.

At this point, you can press the up/down arrow keys to cycle through the three different methods.

Notice that Intellisense does the following:

  • Indicates in bold the next parameter that you should enter
  • Lists a description of the method, if one is available
  • Provides a description of the next parameter

#405 – Equals Method for Equivalence, == Operator for Identity

You can check for equality between two objects by calling the Equals method or by using the == operator.  There are some differences between how the methods work, but both Equals and == can be overloaded in a user-defined type.

You can therefore change the behavior of one of these methods, or both.  The question is–how should these two behaviors work for a custom class?

Roughly speaking, the desired behavior, from a client’s point of view is:

  • Use Equals method to determine value equality, or equivalence–do the two objects represent the same thing?
  • Use == operator to determine reference equality, or identity–do the two references point to exactly the same object?

This argues for overloading Equals for a user-defined reference type, but not overloading the == operator.

This would result in the following behavior:

            Dog d1 = new Dog("Lassie", 7);
            Dog d2 = new Dog("Lassie", 7);

            bool bValueEquality = d1.Equals(d2);    // true
            bool bRefEquality = d1 == d2;    // false

#399 – Overloading Unary Operators

You can overload any of the following unary operators: +, -, !, ~, ++, –, true, false.  A unary operator is an operator that can be applied to a single operand.

Overloading the negation (!) operator allows us to negate an instance of a class.

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

            Dog antiKirby = !kirby;

To overload the operator, we define a new method in our class that takes an instance of a Dog and “negates” it, returning a new instance.

        public static Dog operator !(Dog d1)
        {
            string notName = new string(d1.Name.Reverse().ToArray());

            return new Dog(notName, -1 * d1.Age);
        }

Below is an example of overloading the increment (++) operator.  (We really ought to overload the decrement operator as well).

            Dog olderKirby = kirby++;
        public static Dog operator ++(Dog d1)
        {
            return new Dog(d1.Name, d1.Age++);
        }

#398 – Overloadable Operators

When you define an operator for a class, you are defining the behavior for that operator when acting upon instances of the class.  This is also known as overloading the operator.

You can overload any of the operators listed below.

  • Unary operators  (apply to one operand):  +, -, !, ~, ++, –, true, false
  • Binary operators  (apply to two operands):  +, -, *, /, %, &, |, ^, <<, >>
  • Comparison operators  (apply to two operands): ==, !=, <, >, <=, >=

When you overload the comparison operators, you must overload them in pairs:

  • Implement ==, != together
  • Implement <, > together
  • Implement <=, >= together

#274 – Can’t Overload if Methods Differ Only by ref and out Modifiers

You can overload a method in a class, i.e. define two methods with the same name, if the methods have different lists of parameters.  The parameter lists must differ in the number of parameters or in their types.

For example, we can overload the Dog.Bark method if the parameters differ only in type:

        public void Bark(int numBarks)
        {
            // implementation here
        }

        public void Bark(short numBarks)
        {
            // implementation here
        }

We cannot overload a method if the parameters differ only in a ref vs out modifiers:

        public void FindDog(ref Dog aDog)
        {
            // implementation here
        }

        // Compiler will disallow this overload
        public void FindDog(out Dog aDog)
        {
            // implementation here
        }