jheddings
jheddings

Reputation: 27553

Initializing C# generics using type-specific values

In the following class:

public class Example<T> where T : IComparable {
    private T _min;
    private T _max;

    public Example() {
        // _min = T.MinValue;
        // _max = T.MaxValue;
    }

    public Example(T min, T max) {
        _min = min;
        _max = max;
    }

    public bool Contains(T val) {
        return (val.CompareTo(_min) < 0) && (val.CompareTo(_max) > 0);
    }
}

What would be the best way to initialize the members to their type-specific min & max values in the default constructor? I know this puts another constraint on the allowed types for the generic, but that's fine for my purposes.

Additionally, if a type supported infinite values, such as float or double, is there a way to detect this and set the values accordingly?

Upvotes: 3

Views: 1895

Answers (5)

Sean Vikoren
Sean Vikoren

Reputation: 1094

If you are using C# 3.5, here is an example of using reflection to solve this issue:

public static class GenericLimit<T>
{
    public static readonly T MinValue = (T)MinValue.GetType ().GetField ("MinValue").GetValue (MinValue);
    public static readonly T MaxValue = (T)MaxValue.GetType ().GetField ("MaxValue").GetValue (MaxValue);
}

public class MinMax<T> where T : struct
{
    private readonly T minValue = GenericLimit<T>.MinValue;
    private readonly T maxValue = GenericLimit<T>.MaxValue;

    public T Min { get; private set; }
    public T Max { get; private set; }

    public static bool InRange (T value, T min, T max)
    {
        return (Operator.GreaterThanOrEqual (value, min) && Operator.LessThanOrEqual (value, max));
    }

    public MinMax () { Reset (); }

    public void Update (T n)
    {
        if (Operator.LessThan (n, Min)) Min = n;
        if (Operator.GreaterThan (n, Max)) Max = n;
    }

    public void Reset ()
    {
        Min = maxValue;
        Max = minValue;
    }
}

The generic math is from C# in Depths to (thanks to Jon Skeet and Marc Gravell).

PS Any suggestions for simplifying the reflection will be greatly appreciated.

Upvotes: 0

Thomas Levesque
Thomas Levesque

Reputation: 292355

There is no generic way to know the min and max value for a type. It may not even make sense, depending on the kind of data you're talking about... It is possible to use reflection to find MinValue and MaxValue static members on the type, but these member are not defined on all types.

Upvotes: 0

itowlson
itowlson

Reputation: 74802

There's no constraint that would allow you to do get a MinValue and MaxValue. The only value you can get in a strong-typed way is the default (default(T)).

If you know that the types will have static MinValue and MaxValue properties, you can get at these using Reflection, but could not enforce the safety of this at compile time.

An alternative solution would be to redesign your class slightly: add _isMinSpecified and _isMaxSpecified boolean members, and consult these in your Contains method -- e.g. if neither a min nor a max had been specified, you would always return true.

Upvotes: 9

Ed Swangren
Ed Swangren

Reputation: 124632

Well, I don't think there is an interface available out of the box which could help you. Each concrete type (Int32, float, etc) defines their own min and max values, and they share no common interface for something like this. You could of course define a wrapper class yourself which would accomplish this, but then the there is no reason to use generics at all :)

Additionally, if a type supported infinite values, such as float or double, is there a way to detect this and set the values accordingly?

There is no such thing as an "infinite value" as far as a computer is concerned, and floating point numbers are no more "infinite" than a bit is (they just have more of them).

Upvotes: 0

XXXXX
XXXXX

Reputation: 1096

public Example() {
    _min = default (T);
    _max = default (T);
}

sorry, that's not what you're looking for.

Upvotes: -1

Related Questions