How to access value out of dictionary whose key is complex type?

In writing an insurance premium calculator the basic scheme is as follows: Points are assigned to a predetermined number of attributes, such as car-value, num-incidents-in-past, years-experience-driving etc. Hene, if car worth is $3800, that lies within the 3001 to 4000 range which warrants 30 points in the premium calculation. If num-incidents-in-past is 3 or below, that warrants ZERO points. If 4-5 num-inc then points warranted is 5. If years-exp is between 1-5, that warrants 12 points. The idea is an arbitrary value is being assigned to a range of values for any given number of attributes. The premium calculations is simply tallying up the points warranted for each attribute category and multiplying by some factor i.e 2.5. I am trying to use B. LISKOV'S power of abstractions AND the SRP to neatly assign responsiblities to design a calculator that is extensible and well designed.

Based on the answer provided by drharris here Is there a C# type for representing an integer Range?

How do I access the value out of the following Dictionary whose key is a generic type Range as defined by drharris?

 //************************ABSTRACTIONS************************
   public abstract class AbsPerson
   {
    public virtual AbsPolicy APolicy { get; set; }
    public virtual string ID { get; set; }

    public string Name { get; set; }
    public int Age { get; set; }
    public virtual string Address { get; set; }      
   }

public abstract class AbsPolicy
{ 
  public virtual string PersonID { get; set; } //FK
  public virtual int PropValue { get; set; }
  public virtual int InsGroup { get; set; }           
}

public abstract class AbsValueCategoryCalculator: IEvaluatePolicy
{
    //DATA
    public abstract void InitRange();
    //REFERENCE drharris poster GENERIC TYPE SIGNATURE - public class Range<T> where T : IComparable<T>
    public abstract Dictionary<Range<int>, int> ValueRange {get; set;}
    public abstract int Tally { get; set; }

    //BEHAVIOUR
    public virtual void EvaluatePolicyDetails(AbsPerson person)
    {

    }
}

public interface IEvaluatePolicy
{
    void EvaluatePolicyDetails(AbsPerson person);
}  

//*************************CONCRETIONS**************************
public class CarValueCategoryCalculator : AbsValueCategoryCalculator
{
    public CarValueCategoryCalculator()
    {//ctor
        InitRange();
    }

    public override void InitRange()
    {
        this.ValueRange = new Dictionary<Range<int>, int>();

        this.ValueRange.Add(new Range<int>() { Minimum = 1000, Maximum = 2000 }, 10);
        this.ValueRange.Add(new Range<int>() { Minimum = 2001, Maximum = 3000 }, 20);

        this.ValueRange.Add(new Range<int>() { Minimum = 3001, Maximum = 4000 }, 30);
        this.ValueRange.Add(new Range<int>() { Minimum = 4001, Maximum = 5000 }, 40);
        this.ValueRange.Add(new Range<int>() { Minimum = 5001, Maximum = 6000 }, 50);
        this.ValueRange.Add(new Range<int>() { Minimum = 6001, Maximum = 7000 }, 60);
    }

    public override Dictionary<Range<int>, int> ValueRange
    {
        get; set;
    }

    public override void EvaluatePolicyDetails(AbsPerson person)
    {
           //I am trying to tally the value given wether the cars worth lies within the range      
        if (this.ValueRange.ContainsKey(new Range<int>() { Maximum = person.APolicy.PropValue, Minimum = person.APolicy.PropValue }))
        {
            this.Tally =
        }

        Console.WriteLine("good");            
    }


    public override int Tally
    {
        get;set;
    }

}//end class
Jon Skeet
people
quotationmark

(As noted in comments, Sam's answer points out that a dictionary isn't really what's wanted here - that only finds equal keys, whereas the OP is trying to find a range key that contains a single value. Hash tables just aren't geared up for that.)

You need to either override GetHashCode and Equals in Range<T> (which would be sensible - ideally implementing IEquatable<Range<T>> at the same time) or create a separate type which implements IEqualityComparer<Range<T>> and then pass that to the dictionary constructor.

I would probably do it on the range type, like this:

public sealed class Range<T> : IEquatable<Range<T>>
    where T : IComparable<T>, IEquatable<T>
{
    ...

    public override int GetHashCode()
    {
        int hash = 23;
        hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Minimum);
        hash = hash * 31 + EqualityComparer.Default<T>.GetHashCode(Maximum);
        return hash;
    } 

    public override bool Equals(object other)
    {
        return Equals(other as Range<T>);
    }

    public bool Equals(Range<T> other)
    {
        if (ReferenceEquals(other, this))
        {
            return true;
        }
        if (ReferenceEquals(other, null))
        {
            return false;
        }
        return EqualityComparer<T>.Default.Equals(Minimum, other.Minimum) &&
               EqualityComparer<T>.Default.Equals(Maximum, other.Maximum); 
    }
}

Note that currently the Range<T> type is mutable, however - that's generally a bad idea for dictionary keys. It would be a good idea to make it at least "shallow-immutable" - there's not a lot you can do if the

people

See more on this question at Stackoverflow