Implementation of Equals and GetHashCode for base class Is this a good implementation for Equals and GetHashCode for a base class in C#? If it's not good enough, can you suggest improvements for it, please?

public abstract class Entity&lt;TKey&gt;    //TKey = Type of the Key
{
    private string FullClassName;
    private bool KeyIsNullable;
    private Type BaseClassType;
    private bool KeyIsComplex;

    public abstract TKey Key { get; }    //Key of the object, which determine it's uniqueness

    public Entity()
    {
        FullClassName = GetType().FullName + "#";
        KeyIsNullable = typeof(TKey).IsAssignableFrom(typeof(Nullable));
        BaseClassType = typeof(Entity&lt;TKey&gt;);
        KeyIsComplex= !typeof(TKey).IsPrimitive;
    }

    public override bool Equals(object obj)
    {
        bool result = BaseClassType.IsAssignableFrom(obj.GetType());
        result
            = result
                &amp;&amp; (
                        (
                            (
                                !KeyIsNullable
                                ||
                                (Key != null &amp;&amp; ((Entity&lt;TKey&gt;)obj).Key != null
                            )
                        )
                        &amp;&amp;
                        Key.Equals(((Entity&lt;TKey&gt;)obj).Key )
                    )    // The key is not nullable, or (it's nullable but) both aren't null, and also equal
                    ||
                    (
                        KeyIsNullable
                        &amp;&amp;
                        Key == null
                        &amp;&amp;
                        ((Entity&lt;TKey&gt;)obj).Key == null
                    )
                ); // Or the key is nullable, and both are null
        return result;
    }

    public override int GetHashCode()
    {
        if ((KeyIsNullable&amp;&amp; Key == null) || (!KeyIsNullable&amp;&amp; Key .Equals(default(TKey))))
        {
            return base.GetHashCode();
        }
        string stringRepresentation = FullClassName + ((KeyIsComplex)? Key.GetHashCode().ToString() : Key.ToString());
        return stringRepresentation.GetHashCode();
    }
}


Example of a derived class:

public class Foo : Entity&lt;int&gt;
{
    public virtual int FooId { set; get; }
    public virtual string FooDescription { set; get; }

    public override int Key { get { return FooId; } }
}


Specific and special details to the proposal:


Any instance of a derived class is considered equal to a instance of the base class if they have the same key.
The key could be null.
If the key of the current class and the key of the comparing object are both null, the two objects are considered equal. This is because I am planning to handle just one new object at a time, and if the key is nullable, it will be null for the new object. So if I have two instances with a null key, I will consider them as the same entity.
I think you are overcomplicating things you can say simple this:

    public abstract class Entity&lt;TKey&gt; where TKey : struct 
    {
        public abstract TKey Key { get; }

        protected bool Equals(Entity&lt;TKey&gt; other)
        {
            return Key.Equals(other.Key);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            var asThis = obj as Entity&lt;TKey&gt;;
            return asThis != null &amp;&amp; Equals(asThis);
        }

        public override int GetHashCode()
        {
            return Key.GetHashCode();
        }
    }


No need the type magic
A key cannot be null and it should be a ValueType
An Equals and GetHashCode implementation should be symmetric and fast (your solution is slow and i'm not sure it is symmetric or not)