chanchal1987
chanchal1987

Reputation: 2367

Multiple inheritance issue in C#

This question came to my mind while I am reading the post Why doesn't C# support multiple inheritance? from MSDN Blog.

At first look at the following code:

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class A
    {
        int num;
        public A()
        {
            num = 0;
        }
        public A(int x)
        {
            num = x;
        }
        public override int GetHashCode()
        {
            return num + base.GetHashCode();
        }
    }
    class B : A
    {
        int num;
        public B()
        {
            num = 0;
        }
        public B(int x)
        {
            num = x;
        }
        public override int GetHashCode()
        {
            return num + base.GetHashCode();
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            A a = new A();
            B b = new B();
            Console.Write(a.GetHashCode() + " " + b.GetHashCode());
            Console.Read();
        }
    }
}

Object class is the ultimate base class of all classes. So it is the base class of A and B both in my program and also make A as a base class of B. So B has now two base class, one is A and another is Object. I override one method GetHashCode() of Object Class in class A and B both. But in class B, base.GetHashCode() method returns the return value of GetHashCode() method of class A. But I want this value from Object class. How can I get that?

Upvotes: 5

Views: 1203

Answers (8)

Jon Hanna
Jon Hanna

Reputation: 113382

Yes, this doesn't relate to multiple inheritance at all (incidentally, I miss private inheritance more than multiple inheritance). This question is also quite a horrible thing to think about.

If you have control of class A, then fine:

class A
{
    /*elide the stuff you already have*/
    protected int GetBaseHashCode()
    {
        return base.GetHashCode();
    }
}
class A : B
{
    /*elide stuff already in example*/
    public override int GetHashCode()
    {
        return num + GetBaseHashCode();
    }
}

If you do not:

public class B : A
{
    private static readonly DynamicMethod GRANDPARENT_GET_HASH_CODE;
    static B()
    {
        MethodInfo gpGHC = typeof(object).GetMethod("GetHashCode", BindingFlags.Public | BindingFlags.Instance);

        GRANDPARENT_GET_HASH_CODE = new DynamicMethod("grandParentGHC", typeof(int), new Type[] { typeof(object) }, typeof(object));
        ILGenerator il = GRANDPARENT_GET_HASH_CODE.GetILGenerator();
        il.Emit(OpCodes.Ldarg, 0);
        il.EmitCall(OpCodes.Call, gpGHC, null);
        il.Emit(OpCodes.Ret);
    }
    private int num;
    public B()
    {
        num = 0;
    }
    public B(int x)
    {
        num = x;
    }
    public override int GetHashCode()
    {
        return num + (int)GRANDPARENT_GET_HASH_CODE.Invoke(null, new object[]{this});
    }
}

Frankly, I would put that code in the category of "let us never speak of it again". I assume this is relating to some more general principle, since the hashcodes here are useless anyway, but I'm not sure what that more general principle is. Certainly it can sometimes be annoying when something is hidden from deriving classes we want to get at, but it can be much worse when the opposite happens.

Back in the days of VB6, coders in that language would often have to do rather nasty stuff involving getting the memory address of the v-table used for virtual call lookup, altering the memory protection, and then tweaking the bytes stored there by hand, because in "protecting" users from implementation details they kept some vital things away from them (you could not create enumerators without this technique, only pass on those for other objects).

Thank goodness we are not "protected" to that extent in C#. If I ever have to write code like the answer I gave above for a real project, I'm going to need a few drinks to recover later that evening.

Upvotes: 1

Jeff Mattfield
Jeff Mattfield

Reputation:

You should consider an alternative to calling Object.GetHashCode(). Here's why (from MSDN Library):

The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.

Upvotes: 0

Maja Piechotka
Maja Piechotka

Reputation: 7216

I'm afraid you are mixing normal inheritance with multiple inheritance. Multiple inheritance meand that you have 3 classes A is subclass of B and C but neither B is subclass of C nor C is subclass of B.

Normal inheritance does allow chaining like A is subclass of B which is subclass of C. If you call method it can walk through the classes and check which method to call (in reality it does not check classes one by one). Here B is subclass of A which is subclass of Object. Object happens to have (virtual) method GetHashCode - by overloading it in subclass. The Object method is hidden and (without tricks) cannot be used.

Upvotes: 0

Dave Swersky
Dave Swersky

Reputation: 34820

Getting a hash of the base Object class is irrelevant to the purpose of the method. The whole point of GetHashCode() is to generate a unique (as possible) identity value based on the specific type and state of the object.

The GetHashCode() method uses a default hashing algorithm that can be used to determine instance identity and uniqueness, though uniqueness is not guaranteed. The default algorithm uses the state of the object to generate the hash.

More information: http://msdn.microsoft.com/en-us/library/system.object.gethashcode.aspx

Upvotes: 0

Curt
Curt

Reputation: 454

You could write a protected instance method in class A that exposes GetHashCode() from Object. Then call that protected method in class B.

Upvotes: 4

James Curran
James Curran

Reputation: 103575

No Class B merely has one base class, class A.

To understand, class A really should be written as:

class A : Object

But since that is required, it can be left off.

Upvotes: 2

Timwi
Timwi

Reputation: 66604

B has only one base class, and that is A. A has one base class, and that is object. There is no multiple inheritance; object is only inherited by classes that don’t already inherit from something else.

If you still think you need to call object.GetHashCode(), there is a very hacky workaround to do this in the question How to invoke (non virtually) the original implementation of a virtual method?.

Upvotes: 13

Related Questions