Generic classes with inheritance/equals/comparison operators I would like to greatly reduce verbosity of following code fragment.

What I'd like to do:


Reduce number of occurrences of MaterialRangedParam&lt;Value&gt; and MaterialParam&lt;Value&gt;. C++ has typedef. C# doesn't. Is there keyword for own type of a class?
Remove operator !=, operator ==, GetHashCode and Equals and make compiler generate them for me (the way C++ would do it).


How can I do that?

Additional info:

I'm already aware that clone method offers functionality similar to ICloneable. I have no need to support ICLoneable at the moment.

Usage pattern:
    Those items are going to be stuffed into several lists, arrays and hashtables, compared to each other, assign is going to be called often.

Advice?

public class MaterialParam&lt;Value&gt; where Value: System.IEquatable&lt;Value&gt;{
    public string name = "";
    public string shaderValueName = "";
    public Value value;// = Value();
    public void assignFrom(MaterialParam&lt;Value&gt; other){
        name = other.name;
        shaderValueName = other.shaderValueName;
        value = other.value;
    }

    public MaterialParam&lt;Value&gt; clone(){
        var result = new MaterialParam&lt;Value&gt;();
        result.assignFrom(this);
        return result;
    }

    public override bool Equals(object obj){
        if(!(obj is MaterialParam&lt;Value&gt;))
            return false;

        MaterialParam&lt;Value&gt; other = (MaterialParam&lt;Value&gt;)obj;
        if((System.Object)other == null){
            return false;
        }           

        return (this.name == other.name) &amp;&amp; 
            (this.shaderValueName == other.shaderValueName) &amp;&amp;
                (this.value.Equals(other.value));
    }

    public override int GetHashCode(){
        return name.GetHashCode() ^ shaderValueName.GetHashCode() 
            ^ value.GetHashCode();
    }

    public static bool operator !=(MaterialParam&lt;Value&gt; a, MaterialParam&lt;Value&gt; b){
        return !(a == b);
    }

    public static bool operator ==(MaterialParam&lt;Value&gt; a, MaterialParam&lt;Value&gt; b){
        return a.Equals(b);
    }
};

public class MaterialRangedParam&lt;Value&gt;: MaterialParam&lt;Value&gt; where Value: System.IEquatable&lt;Value&gt;{
    public Value minValue;// = Value();
    public Value maxValue;// = Value();
    public void assignFrom(MaterialRangedParam&lt;Value&gt; other){
        base.assignFrom(other);
        minValue = other.minValue;
        maxValue = other.maxValue;
    }

    new public MaterialRangedParam&lt;Value&gt; clone(){
        var result = new MaterialRangedParam&lt;Value&gt;();
        result.assignFrom(this);
        return result;
    }

    public override bool Equals(object obj){
        if (!base.Equals(obj))
            return false;

        if(!(obj is MaterialRangedParam&lt;Value&gt;))
            return false;

        MaterialRangedParam&lt;Value&gt; other = (MaterialRangedParam&lt;Value&gt;)obj;
        if((System.Object)other == null){
            return false;
        }           

        return (minValue.Equals(other.minValue)) &amp;&amp; (maxValue.Equals(other.maxValue));
    }

    public override int GetHashCode(){
        return base.GetHashCode() ^ minValue.GetHashCode() ^ maxValue.GetHashCode();
    }

    public static bool operator !=(MaterialRangedParam&lt;Value&gt; a, MaterialRangedParam&lt;Value&gt; b){
        return !(a == b);
    }

    public static bool operator ==(MaterialRangedParam&lt;Value&gt; a, MaterialRangedParam&lt;Value&gt; b){
        return a.Equals(b);
    }
}
This code looks very Java-like in its style and implementation. Maybe C#1.0 at its best. There are a number of stylistic and idiomatic changes I'd make to make these two classes "play well" in the C# / .NET world of 2015. Without going into exhaustive detail, I employed object immutability, parameterized constructors, implementing IClonaeble, utilizing properties, correctly implementing Equals and ==.

With regards to the two things that  you'd like to do, sorry, neither are possible (nor really desirable) with C# for various reasons that you can find on MSDN.

The code:

public class MaterialParam&lt;TValue&gt; where TValue : IEquatable&lt;TValue&gt;, ICloneable
{
    public readonly string name = string.Empty;

    public readonly string shaderValueName = string.Empty;

    public readonly TValue value; // = Value();

    public MaterialParam()
    {
    }

    public MaterialParam(string name, string shaderValueName, TValue value)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }

        if (shaderValueName == null)
        {
            throw new ArgumentNullException("shaderValueName");
        }

        if (value == null)
        {
            throw new ArgumentNullException("value");
        }

        this.name = name;
        this.shaderValueName = shaderValueName;
        this.value = value;
    }

    public MaterialParam(MaterialParam&lt;TValue&gt; other)
    {
        if (other == null)
        {
            throw new ArgumentNullException("other");
        }

        this.name = other.name;
        this.shaderValueName = other.shaderValueName;
        this.value = other.value;
    }

    public string Name
    {
        get
        {
            return this.name;
        }
    }

    public string ShaderValueName
    {
        get
        {
            return this.shaderValueName;
        }
    }

    public TValue Value
    {
        get
        {
            return this.value;
        }
    }

    public static bool operator ==(MaterialParam&lt;TValue&gt; a, MaterialParam&lt;TValue&gt; b)
    {
        if (ReferenceEquals(a, b))
        {
            return true;
        }

        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }

        return a.Equals(b);
    }

    public static bool operator !=(MaterialParam&lt;TValue&gt; a, MaterialParam&lt;TValue&gt; b)
    {
        return !(a == b);
    }

    public MaterialParam&lt;TValue&gt; Clone()
    {
       return new MaterialParam&lt;TValue&gt;(this);
    }

    public override bool Equals(object obj)
    {
        if (!(obj is MaterialParam&lt;TValue&gt;))
        {
            return false;
        }

        var other = (MaterialParam&lt;TValue&gt;)obj;

        return (this.name == other.Name)
            &amp;&amp; (this.shaderValueName == other.ShaderValueName)
            &amp;&amp; this.value.Equals(other.Value);
    }

    public override int GetHashCode()
    {
        return this.name.GetHashCode()
            ^ this.shaderValueName.GetHashCode()
            ^ this.value.GetHashCode();
    }
}

public class MaterialRangedParam&lt;TValue&gt; : MaterialParam&lt;TValue&gt; where TValue : IEquatable&lt;TValue&gt;, ICloneable
{
    public readonly TValue minValue; // = Value();

    public readonly TValue maxValue; // = Value();

    public MaterialRangedParam(TValue minValue, TValue maxValue)
    {
        if (minValue == null)
        {
            throw new ArgumentNullException("minValue");
        }

        if (maxValue == null)
        {
            throw new ArgumentNullException("maxValue");
        }

        this.minValue = minValue;
        this.maxValue = maxValue;
    }

    public MaterialRangedParam(MaterialRangedParam&lt;TValue&gt; other) : base(other)
    {
        if (other == null)
        {
            throw new ArgumentNullException("other");
        }

        this.minValue = other.MinValue;
        this.maxValue = other.MaxValue;
    }

    public TValue MinValue
    {
        get
        {
            return this.minValue;
        }
    }

    public TValue MaxValue
    {
        get
        {
            return this.maxValue;
        }
    }

    public static bool operator ==(MaterialRangedParam&lt;TValue&gt; a, MaterialRangedParam&lt;TValue&gt; b)
    {
        if (ReferenceEquals(a, b))
        {
            return true;
        }

        if (((object)a == null) || ((object)b == null))
        {
            return false;
        }

        return a.Equals(b);
    }

    public static bool operator !=(MaterialRangedParam&lt;TValue&gt; a, MaterialRangedParam&lt;TValue&gt; b)
    {
        return !(a == b);
    }

    public new MaterialRangedParam&lt;TValue&gt; Clone()
    {
        return new MaterialRangedParam&lt;TValue&gt;(this);
    }

    public override bool Equals(object obj)
    {
        if (!(obj is MaterialRangedParam&lt;TValue&gt;))
        {
            return false;
        }

        var other = (MaterialRangedParam&lt;TValue&gt;)obj;

        return base.Equals(other) &amp;&amp; this.minValue.Equals(other.MinValue) &amp;&amp; this.maxValue.Equals(other.MaxValue);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode() ^ this.minValue.GetHashCode() ^ this.maxValue.GetHashCode();
    }
}