Implementing numeric limit class - c#

I am new to C# and trying to implement a numeric limit class as :
internal class NumericLimit<TValue> where TValue : IComparable
{
public NumericLimit(TValue min, TValue max)
{
this.Max = max;
this.Min = min;
}
internal TValue Max { get; }
internal TValue Min { get; }
internal bool WithinBounds(TValue min, TValue max)
{
if (min.CompareTo(this.Min) <= 0 &&
max.CompareTo(this.Max) >= 0)
return true;
return false;
}
internal bool LessThan(TValue value)
{
return (value.CompareTo(this.Max) > 0);
}
internal bool GreaterThan(TValue value)
{
return (value.CompareTo(this.Min) < 0);
}
internal bool Contains(TValue value)
{
if (value.CompareTo(this.Max) == 0 ||
value.CompareTo(this.Min) == 0)
return true;
return (value.CompareTo(this.Min) > 0) &&
(value.CompareTo(this.Max) < 0);
}
internal bool Defined()
{
return true;
}
}
The problem is how to implement Defined() function. I want the NumericLimit to be invalid/undefined when both Min and Max values are -1.
Like, for NumericLimit<long> the limit is undefined when both Min and Max are -1L.
And for NumericLimit<int> the limit is undefined when both Min and Max are -1.
How to implement 'Defined' in a way that correctly represents negative one for TValue type ?

What if after some time you decide to use NumericLimit<double> or some other type for T that will not accept value of -1? I suggest using special IsDefined flag and adding static method for constructing undefined limit:
internal class NumericLimit<TValue> where TValue : IComparable
{
internal bool IsDefined { get; }
public NumericLimit(TValue min, TValue max)
{
this.Max = max;
this.Min = min;
IsDefined = true;
}
private NumericLimit()
{
IsDefined = false;
}
public static NumericLimit<TValue> Undefined()
{
return new NumericLimit<TValue>();
}
// ...
}

Related

C# Generics - Manage each type adding 1

I'm new using Generics.
My function GetValuesGenerics give me some error:
Cannot implicitly convert type 'ImproveMe.ViewModel.ControlYourWeight.DateTimeValuesGenerics' to 'ImproveMe.ViewModel.ControlYourWeight.ValuesGenerics<T>'
My Objective is that I give a min and maxValue and it generates me a range of value between min and max. I want to call the generator from an other class using Generics too. I don't really know if I have double or DateTime!
Could you help me out?
public static class ValuesGenericsGenerator<T>
{
public static ValuesGenerics<T> GetValuesGenerics()
{
if (typeof(T) == typeof(double))
{
return new DoubleValuesGenerics(1,1); ;
}
else if (typeof(T) == typeof(DateTime))
{
return new DateTimeValuesGenerics(DateTime.Now, DateTime.Now.AddDays(5));
}
else
{
return null;
}
}
}
public abstract class ValuesGenerics<T>
{
protected T minValue;
protected T maxValue;
public ValuesGenerics(T minValue, T maxValue)
{
this.minValue = minValue;
this.maxValue = maxValue;
}
public abstract List<T> GenerateValues();
}
public class DoubleValuesGenerics : ValuesGenerics<double>
{
public DoubleValuesGenerics(double minValue, double maxValue)
: base(minValue, maxValue)
{
}
public override List<double> GenerateValues()
{
List<double> values = new List<double>();
do
{
values.Add(minValue);
minValue++;
}
while (minValue <= maxValue);
return values;
}
}
public class DateTimeValuesGenerics : ValuesGenerics<DateTime>
{
public DateTimeValuesGenerics(DateTime minValue, DateTime maxValue)
: base(minValue, maxValue)
{
}
public override List<DateTime> GenerateValues()
{
List<DateTime> values = new List<DateTime>();
do
{
values.Add(minValue);
minValue.AddDays(1);
}
while (minValue <= maxValue);
return values;
}
}
You can do this by first casting the result of GetValuesGenerics() to a common, non generic base class of your ValuesGenericsGenerator<T> (e.g. object, for all c# objects).
public static class ValuesGenericsGenerator<T>
{
public static ValuesGenerics<T> GetValuesGenerics()
{
object result;
if (typeof(T) == typeof(double))
{
result = new DoubleValuesGenerics(1,1);
}
else if (typeof(T) == typeof(DateTime))
{
result = new DateTimeValuesGenerics(DateTime.Now, DateTime.Now.AddDays(5));
}
else
{
return null;
}
return (ValuesGenerics<T>) result;
}
}
Note:
Your current code allows you to only once call GenerateValues() and produces an infinite loop when using the DateTime version! You should change it to
public override List<double> GenerateValues()
{
List<double> values = new List<double>();
double val = minValue;
do
{
values.Add(val);
val++;
}
while (val <= maxValue);
return values;
}
...
public override List<DateTime> GenerateValues()
{
List<DateTime> values = new List<DateTime>();
DateTime val = minValue;
do
{
values.Add(val);
val = val.AddDays(1);
}
while (minValue <= maxValue);
return values;
}
You need to explicitly tell compiler the return type you are expecting or it cannot determine the return type if it is ValuesGenerics or ValuesGenerics or something else.
Not sure about the exact notation but it should be something like this:
public static class ValuesGenericsGenerator<T, TValues> where TValues : ValuesGenerics<T>
{
public static TValues GetValuesGenerics()
{
// Do something.
}
}

How to implement IComparable<Time> in my Struct?

My code includes struct called Time.
I would like to implement IComparable<Time> interface in my struct to compare two variables of type 'Time'.
I've already did it with IEquatable and it works, but I can't figure out how to do it with IComparable.
Since Time consists of three variables (hours, min, sec) I can't simply consider each case in if. Or can I? Could you give me a hint how to code it? Thank you.
{
public struct Time : IEquatable<Time>, IComparable<Time>
{
private byte hours, minutes, seconds;
public byte Hours { get { return hours; } }
public byte Minutes { get { return minutes; } }
public byte Seconds { get { return seconds; } }
public Time(byte hh, byte mm, byte ss)
{
if (hh < 0 || hh > 24)
throw new ArgumentOutOfRangeException();
if (mm < 0 || mm > 60)
throw new ArgumentOutOfRangeException();
if (ss < 0 || ss > 60)
throw new ArgumentOutOfRangeException();
this.hours = hh;
this.minutes = mm;
this.seconds = ss;
}
public Time(byte hh, byte mm) : this(hh, mm, default(byte)) { }
public Time(byte hh) : this(hh, default(byte), default(byte)) { }
public Time(string hms)
{
string[] arr = hms.Split(':');
this.hours = Convert.ToByte(arr[0]);
this.minutes = Convert.ToByte(arr[1]);
this.seconds = Convert.ToByte(arr[2]);
}
public override string ToString()
{
return Hours + ":" + Minutes + ":" + Seconds;
}
public override bool Equals(object t)
{
if (t == null || this.GetType() != t.GetType()) return false;
return (this.Hours == ((Time)t).Hours &&
this.Minutes == ((Time)t).Minutes &&
this.Seconds == ((Time)t).Seconds);
}
public override int GetHashCode()
{
return this.GetHashCode();
}
// IEquatable
public bool Equals(Time other)
{
return this.Equals((object)other);
}
public static bool operator == (Time t1, Time t2)
{
return t1.Equals(t2);
}
public static bool operator !=(Time t1, Time t2)
{
return !t1.Equals(t2);
}
// IComparable
public int CompareTo(Time other)
{
if (this == other)
return 0;
// Code that compares two variables
}
public static bool operator > (Time t1, Time t2)
{
return t1.CompareTo(t2) == 1;
}
public static bool operator < (Time t1, Time t2)
{
return t1.CompareTo(t2) == -1;
}
public static bool operator >= (Time t1, Time t2)
{
return t1.CompareTo(t2) >= 0;
}
public static bool operator <= (Time t1, Time t2)
{
return t1.CompareTo(t2) <= 0;
}
}
}
public int CompareTo(Time other)
{
var by_hour = this.Hours - other.Hours;
if (by_hour != 0)
return by_hour;
var by_minute = this.Minutes - other.Minutes;
if (by_minute != 0)
return by_minute;
return this.Seconds - other.Seconds;
}
Also change all places where you use the Compare method to account for the fact that it can return non-zero values other than 1 and -1.

How do you create your own DataType?

I would like to create my own DataType called positiveInteger.
I know what you are thinking?
You are thinking that I should use uint here.
But uint contains 0 and I want only positive numbers.
Now you may tell me that Create a class called positiveInteger.
Yes, I can create a Class called positiveIntegerbut I don't know how to implement that class such that this new DataType accepts only positive integer values?
If you want to be able to "accept" values, which are (mostly) compiled as constant int values, then you'll need to implement an implicit conversion to positiveInteger from int
public class positiveInteger
{
public static implicit operator positiveInteger(int source)
{
if(source <= 0) throw new ArgumentOutOfRangeException();
}
}
This will allow you to assign a positiveInteger like so
positiveInteger number = 5;
It will also, however, make it possible to assign an int value
int i = 5;
positiveInteger number = i; // This will throw an exception when i <= 0
An example imlementation could be:
public struct PositiveInteger : IEquatable<PositiveInteger>, IComparable<PositiveInteger>
{
public PositiveInteger(uint value)
{
if (value <= 0) throw new ArgumentOutOfRangeException();
_value = value;
}
public uint Value { get { return _value == 0 ? 1 : _value; } }
private readonly uint _value;
public static implicit operator PositiveInteger(uint value)
{
return new PositiveInteger(value);
}
public static implicit operator uint(PositiveInteger value)
{
return value.Value;
}
public static PositiveInteger operator +(PositiveInteger value1, PositiveInteger value2)
{
var result = value1.Value + value2.Value;
if (result < value1.Value || result < value2.Value)
{
throw new ArgumentOutOfRangeException(); //overflow
}
return result;
}
public static PositiveInteger operator -(PositiveInteger value1, PositiveInteger value2)
{
if (value1.Value < value2.Value) throw new ArgumentOutOfRangeException();
return value1.Value - value2.Value;
}
public override bool Equals(object obj)
{
if (obj is PositiveInteger == false) return false;
return Equals((PositiveInteger)obj);
}
public bool Equals(PositiveInteger other)
{
return Value == other.Value;
}
public override int GetHashCode()
{
return (int)Value;
}
public int CompareTo(PositiveInteger other)
{
if (Value == other.Value) return 0;
return Value < other.Value ? -1 : 1;
}
public override string ToString()
{
return Value.ToString(CultureInfo.InvariantCulture);
}
}
And a small test:
void Test()
{
var list = new List<PositiveInteger> {5, 1, 3};
list.Sort(); // 1,3,5
var a = new PositiveInteger(1);
var b = new PositiveInteger(2);
var c = a + b; // = 3
var d = c - b; // = 1
var e = d - a; // throws ArgumentOutOfRangeException
}
Try this for your constructor. But it is still not a good idea because you should still validate all data before you use it. Just like checking that a denominator is not zero before blindly dividing.
public class PositiveInteger {
private uint _value;
public PositiveInteger(int x) {
if (x < 1) {
throw new Exception("Invalid value. Value is not positive.");
}
_value = x;
}
}

How to specify to validate this situation with generics?

I'm trying to validate this class: min >= max. I realized using generics I can't use the comparators.
This is my generic class.
public class Range<T>
{
public T MinValue { get; set; }
public T MaxValue { get; set; }
public Range() { }
public Range(T min, T max)
{
this.MinValue = min;
this.MaxValue = max;
}
public override bool Equals(object obj)
{
if (obj == null) return false;
var other = obj as Range<T>;
return this.MinValue.Equals(other.MinValue) &&
this.MaxValue.Equals(other.MaxValue);
}
public override string ToString()
{
return string.Format("{0},{1}", this.MinValue, this.MaxValue);
}
}
T datatype can be only numbers, is there a way to accept just numbers and accept the <=?
No, you can't constrain generics to numbers, but you can constrain T to IComparable<T> and then use CompareTo()
public class Range<T> where T : IComparable<T>
{
....
}
Then you can say:
if (min.CompareTo(max) >= 0)...
And throw a validation exception or whatever validation you'd like. You can use the same thing to make sure value is >= min and <= max.
if (value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0)...
public class Range<T> where T : IComparable<T>
{
...
public bool Check(T value)
{
return value.CompareTo(min) >= 0 && value.CompareTo(max) <= 0;
}
}
If you range between 0 and 10, and want 0, 10 to fail (exclude min and max) - simply replace ">=" with ">" and "<=" with "<".
I would also recommend changing in the Equals override from:
return this.MinValue.Equals(other.MinValue) &&
this.MaxValue.Equals(other.MaxValue);
to this:
return this.MinValue.CompareTo(other.MinValue) == 0 &&
this.MaxValue.CompareTo(other.MaxValue) == 0;

Need help avoiding code duplication across multiple method signatures

I have a need to restrict certain numbers to valid ranges in my application. I created delegates to handle this. I don't know if this is the right way to do it; I'm running into something that feels wrong.
public delegate int RestrictInteger(int minimum, int maximum, int value);
public delegate decimal RestrictDecimal(decimal minumum, decimal maximum, decimal value);
class GameMath
{
public static int RestrictNumber(int minimum, int maximum, int value)
{
if (value < minimum) { value = minimum; }
else if (value > maximum) { value = maximum; }
return value;
}
public static decimal RestrictNumber(decimal minimum, decimal maximum, decimal value)
{
if (value < minimum) { value = minimum; }
else if (value > maximum) { value = maximum; }
return value;
}
}
public class SomeClass
{
public int aValue { get; set; }
public void SetValue(int value)
{
RestrictInteger doRestrict = new RestrictInteger(GameMath.RestrictNumber);
this.aValue = doRestrict(0, 100, value);
}
}
On one hand, it seems like if I added more signatures, then I'd want to be able to do different things with them (say, conversions, or rounding, etc.). On the other hand, between these two signatures, the code is precisely the same. Is that okay, or is there some way to write one operation which applies to both these cases, even if other cases might use different operations?
Yes, you can do this with generics - although not with < and >. You should use the fact that these types implement IComparable<T> for themselves:
public static T RestrictNumber<T>(T min, T max, T value) where T : IComparable<T>
{
return value.CompareTo(min) < 0 ? min
: value.CompareTo(max) > 0 ? max
: value;
}
(You could still use your original code here - I rather like this sort of use of the conditional operator though; it satisfies my growing functional tendencies.)
(I'm late to the party, but wanted to take a shot at it)
I think this syntax reads well:
Restrict.Value(x).ToBetween(0, 100)
You can do it by defining a restriction interface:
public interface IRestrictable<T> where T : IComparable<T>
{
T ToBetween(T minimum, T maximum);
}
Then, define a static class which provides the implementation and a method which infers the type:
public static class Restrict
{
public static IRestrictable<T> Value<T>(T value) where T : IComparable<T>
{
return new Restricter<T>(value);
}
private sealed class Restricter<T> : IRestrictable<T> where T : IComparable<T>
{
private readonly T _value;
internal Restricter(T value)
{
_value = value;
}
public T ToBetween(T minimum, T maximum)
{
// Yoink from Jon Skeet
return _value.CompareTo(minimum) < 0
? minimum
: _value.CompareTo(maximum) > 0 ? maximum : value;
}
}
}
Depending on how you will use these numbers, there may be instances when a type with an implicit operator will be useful.
It allows you to use common comparison and unary operators, such as < <= > >= + -, and to mix usage between the T type and the RestrictedNumber type, so, for example, you can pass a RestrictedNumber to any method that expects a double, all the while still holding on to the initial value that may have been out of range.
You never have to call any methods to perform restriction or casting -- everything can be set upon declaration.
See the second class below for usage examples and notes.
Having misplaced Occam's Razor:
public class RestrictedNumber<T> : IEquatable<RestrictedNumber<T>>, IComparable<RestrictedNumber<T>>
where T: IEquatable<T>,IComparable<T>
{
T min;
T max;
readonly T value;
public RestrictedNumber(T min, T max, T value)
{
this.min = min;
this.max = max;
this.value = value;
}
public T UnrestrictedValue
{
get{ return value; }
}
public static implicit operator T(RestrictedNumber<T> n)
{
return get_restricted_value(n);
}
public static implicit operator RestrictedNumber<T>(T value)
{
return new RestrictedNumber<T>(value, value, value);
}
static T get_restricted_value(RestrictedNumber<T> n)
{
// another yoink from Jon Skeet
return n.value.CompareTo(n.min) < 0 ? n.min
: n.value.CompareTo(n.max) > 0 ? n.max
: n.value;
}
T restricted_value
{
get { return get_restricted_value(value); }
}
public T Min // optional to expose this
{
get { return this.min; }
set { this.min = value; } // optional to provide a setter
}
public T Max // optional to expose this
{
get { return this.max; }
set { this.max = value; } // optional to provide a setter
}
public bool Equals(RestrictedNumber<T> other)
{
return restricted_value.Equals(other);
}
public int CompareTo(RestrictedNumber<T> other)
{
return restricted_value.CompareTo(other);
}
public override string ToString()
{
return restricted_value.ToString();
}
}
public class RestrictedNumberExercise
{
public void ad_hoc_paces()
{
// declare with min, max, and value
var i = new RestrictedNumber<int>(1, 10, 15);
Debug.Assert(i == 10d);
Debug.Assert(i.UnrestrictedValue == 15d);
// declare implicitly
// my implementation initially sets min and max equal to value
RestrictedNumber<double> d = 15d;
d.Min = 1;
d.Max = 10;
Debug.Assert(i == 10d); // compare with other, "true" doubles
Debug.Assert(i.UnrestrictedValue == 15d); // still holds the original value
RestrictedNumber<decimal> m = new RestrictedNumber<decimal>(55.5m,55.5m,55.499m);
Debug.Assert(m == 55.5m);
Debug.Assert(m > m.UnrestrictedValue); // test out some other operators
Debug.Assert(m >= m.UnrestrictedValue); // we didn't have to define these
Debug.Assert(m + 10 == 65.5m); // you even get unary operators
RestrictedNumber<decimal> other = 50m;
Debug.Assert(m > other); // compare two of these objects
Debug.Assert(other <= m); // ...again without having to define the operators
Debug.Assert(m - 5.5m == other); // unary works with other Ts
Debug.Assert(m + other == 105.5m); // ...and with other RestrictedNumbers
Debug.Assert(55.5m - m == 0);
Debug.Assert(m - m == 0);
// passing to method that expects the primitive type
Func<float,float> square_float = f => f * f;
RestrictedNumber<float> restricted_float = 3;
Debug.Assert(square_float(restricted_float) == 9f);
// this sort of implementation is not without pitfalls
// there are other IEquatable<T> & IComaparable<T> types out there...
var restricted_string = new RestrictedNumber<string>("Abigail", "Xander", "Yolanda");
Debug.Assert(restricted_string == "Xander"); // this works
//Debug.Assert(restricted_string >= "Thomas"); // many operators not supported here
var pitfall = new RestrictedNumber<int>(1, 100, 200);
Debug.Assert(pitfall == 100);
pitfall = 200;
// Debug.Assert(pitfall == 100);
// FAIL -- using the implicit operator is effectively
// a factory method that returns a NEW RestrictedNumber
// with min and max initially equal to value (in my implementation)
Debug.Assert(pitfall == 200);
pitfall = 10;
Debug.Assert(pitfall.Min == 10 && pitfall.Max == 10);
pitfall++;
Debug.Assert(pitfall == 11); // d'oh!
Debug.Assert(pitfall.Min == 11 && pitfall.Max == 11); // "it goes up to eleven"
// if you need to change the input value for an existing
// RestrictedNumber, you could expose a SetValue method
// and make value not readonly
}
}
You can combine this approach with Bryan's fluent-ish interface and take this pretty far (though you probably don't really need to and this is all crazy overkill).
var n = Restrict<int>._(25).to_be.greater_than(50);
var p = Restrict<double>._(1234.567).to_be.greater_than(0d).and.less_than(50000d)

Categories

Resources