Need help avoiding code duplication across multiple method signatures - c#

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)

Related

How to define two possible data type for property

I am trying to define an operator overloads in C# for 2 classes: Fraction and BasicFraction.
On the outside, they act the same, but internally Fraction uses PrimeFactorization (stores number as a list of prime factors) and BasicFraction uses int for storing the nominator and denominator.
They would follow this interface (if I use JSDoc type definitions):
public interface IFraction
{
public (int|Primefactoriztion) a; // nominator
public (int|Primefactoriztion) b; // denominator
}
But since I can't do that like this, is there a simple way to use Fraction and BasicFraction interchangeably?
I can define all operator overloads for evaluating interactions between int and PrimeFactorization. However, I don't know how to tell C# to accept both to be passed to methods.
Tl;dr: how to make one property allow 2 data types?
Notes:
I am new to advanced C# (I know static typing and basic OOP, but nothing more). I am coming from JS and Python background.
I know they are probably good libraries with this functionality. I am writing this in order to learn C#, not for production.
Edit:
Currently, PrimeFactorization stores factors and their power in Dictionary<int, BasicFraction> (I would use Fraction, but it causes recursion; this is basically the only usage of BasicFraction).
What you have in mind is called discriminated union and is not available as language feature in C#.
I would use a hybrid approach where a fraction would contain nominator and denominator as int plus prime factor lists as read-only properties. You could initialize the fraction with either ints or prime factor lists through two constructors. The missing entries would be calculated lazily to minimize the calculation overhead.
Making the properties read-only increases the robustness of the code. Especially if you are using structs. See Mutating readonly structs (Eric Lippert's blog: Fabulous adventures in coding). But note that the struct is still mutable because of the lazy evaluation.
public struct Fraction
{
public Fraction(int nominator, int denominator)
{
_nominator = nominator;
_denominator = denominator;
_nominatorPrimeFactors = null;
_denominatorPrimeFactors = null;
}
public Fraction(IList<int> nominatorPrimeFactors, IList<int> denominatorPrimeFactors)
{
if (nominatorPrimeFactors == null || nominatorPrimeFactors.Count == 0) {
throw new ArgumentNullException(
$"{nameof(nominatorPrimeFactors)} must be a non-null, non-empty list");
}
if (denominatorPrimeFactors == null || denominatorPrimeFactors.Count == 0) {
throw new ArgumentNullException(
$"{nameof(denominatorPrimeFactors)} must be a non-null, non-empty list");
}
_nominator = null;
_denominator = null;
_nominatorPrimeFactors = nominatorPrimeFactors;
_denominatorPrimeFactors = denominatorPrimeFactors;
}
private int? _nominator;
public int Nominator
{
get {
if (_nominator == null) {
_nominator = _nominatorPrimeFactors.Aggregate(1, (x, y) => x * y);
}
return _nominator.Value;
}
}
private int? _denominator;
public int Denominator
{
get {
if (_denominator == null) {
_denominator = _denominatorPrimeFactors.Aggregate(1, (x, y) => x * y);
}
return _denominator.Value;
}
}
private IList<int> _nominatorPrimeFactors;
public IList<int> NominatorPrimeFactors
{
get {
if (_nominatorPrimeFactors == null) {
_nominatorPrimeFactors = Factorize(Nominator);
}
return _nominatorPrimeFactors;
}
}
private IList<int> _denominatorPrimeFactors;
public IList<int> DenominatorPrimeFactors
{
get {
if (_denominatorPrimeFactors == null) {
_denominatorPrimeFactors = Factorize(Denominator);
}
return _denominatorPrimeFactors;
}
}
private static List<int> Factorize(int number)
{
var result = new List<int>();
while (number % 2 == 0) {
result.Add(2);
number /= 2;
}
int factor = 3;
while (factor * factor <= number) {
if (number % factor == 0) {
result.Add(factor);
number /= factor;
} else {
factor += 2;
}
}
if (number > 1) result.Add(number);
return result;
}
public override string ToString()
{
if (_nominatorPrimeFactors == null && _denominatorPrimeFactors == null) {
return $"{_nominator}/{_denominator}";
}
string npf = ListToString(_nominatorPrimeFactors);
string dpf = ListToString(_denominatorPrimeFactors);
if (_nominator == null && _denominator == null) {
return $"({npf}) / ({dpf})";
}
return $"{_nominator}/{_denominator}, ({npf}) / ({dpf})";
static string ListToString(IList<int> primeFactors)
{
if (primeFactors == null) {
return null;
}
return String.Join(" * ", primeFactors.Select(i => i.ToString()));
}
}
}
Note that declaring the prime factor lists a IList<int> allows you to initialize the fraction with either int[] or List<int>.
But it is worth considering whether the prime factors really need to be stored. Isn't it enough to calculate them when required by some calculation?
You want a discriminated union type. C# does not support them natively as a first-class language feature but you can hack-it using OneOf: https://github.com/mcintyre321/OneOf
So you would end-up with:
public interface IFraction
{
public OneOf< int, Primefactoriztion > a; // nominator
public OneOf< int, Primefactoriztion > b; // denominator
}
but it's still a code-smell. I think you need to reconsider your entire approach. Also, using interfaces to represent values probably isn't a good idea (due to all the heap-allocation), especially because your a and b members appear to be mutable.
A better idea is to change your Primefactoriztion type (which I hope and assume is a struct, not a class) to support implicit conversion from int and some member for explicit conversion to int if the operation is unsafe (e.g. if the value is not an integer):
struct Primefactoriztion
{
public static implicit operator int(Primefactoriztion self)
{
return ...
}
}
That way you can safely eliminate the OneOf<int and use just Primefactoriztion:
public interface IFraction
{
public Primefactoriztion a; // nominator
public Primefactoriztion b; // denominator
}

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;

Interval data type for C# .NET?

I'm looking an interval data type for .NET 4.0. For example the interval (a,b], all point x such that a<x<=b.
What i would like to be able to do are create intervals with the following properites:
Closed and open ends
Unbounded intervals, fully unbounded, and right/left unbounded.
With these I would like to do thing like:
Check if a point is in a interval.
Check if two intervals overlap.
Merge two overlapping intervals to a single interval.
Check if a collection of intervals covers a single interval.
Etc :)
Would be nice if I could work with both numerical datatype and datetimes.
I know that the logic is pretty straight forward, but I see no reason that I would be the first one to need such a thing either.
EDIT 2019: As of C# 8.0/.NET Core 3.x/.NET Standard 2.1 there is now a System.Range that provides minimal interval functionality with endpoints. I'm leaving the rest of this answer as-is.
As others have stated, there are no integrated interval type. Depending on the needs of your project, a simple Tuple<T1, T2> or call to Enumerable.Range with a few additional lines of code might suffice. The HashSet<T> contains set operation methods, such as UnionWith, IntersectWith and more, but still stores all the items, not just the endpoints.
Many implementations can be found online. There is the basic generic Range class part of the Microsoft Research Dynamic Data Display project and another from Kevin Gadd. The AForge project contains a non-generic IntInterval/DoubleInterval implementation. Other (1, 2) SO questions might also be of interest. Andy Clymer has an interesting dynamically compiled implementation on his blog. More complete solutions can be found on CodeProject, in Jon Skeet's book and From Russia with Love. There seems to be a few (1, 2) commercial solutions as well. I've seen others before that I can't find at the moment.
Whatever you do, please watch out when using a generic interval type. It's actually hard to write a correct monolithic generic interval class because integer and floating point intervals have different mathematical properties. For example all integer intervals can be represented with closed endpoints and the pair [1,2] [3,6] can be considered as contiguous, equivalent to [1,6]. None of this is true with floating points intervals. See Wikipedia for details. A group of classes might be better, with an abstract generic base class and typed derived classes IntInterval or DoubleInterval to implement the different behaviors.
Aside from the math, there are a few more implementation difficulties with generic interval types. It's not possible to easily do arithmetic with generics in C#, and there is floating point NaN and rounding errors to take care of. See the Boost library documentation for Interval<T> for more on this. (A lot of it translates to C# and .NET.) Luckily many operations can be done with just IComparable<T>.
As I mentioned before, the choice of what is appropriate in terms of functionality and correctness all depends on the requirements of your projects.
To get you started:
public class Interval<T> where T : struct, IComparable
{
public T? Start { get; set; }
public T? End { get; set; }
public Interval(T? start, T? end)
{
Start = start;
End = end;
}
public bool InRange(T value)
{
return ((!Start.HasValue || value.CompareTo(Start.Value) > 0) &&
(!End.HasValue || End.Value.CompareTo(value) > 0));
}
}
The following allows open ended ranges of any type that implements IComparable. An obvious extension would be to allow you to pass your own comparer (in much the same way that Hashset<T> does.
The range in this case is a<=x
It includes overlap and merge. Other functions should be reasonably easy to add.
public class Interval<T> where T : IComparable
{
public T Start { get; private set; }
public T End { get; private set; }
public bool HasStart { get; private set; }
public bool HasEnd { get; private set; }
private Interval()
{
}
public bool Overlaps(Interval<T> other)
{
if (this.HasStart && other.IsInRange(this.Start))
return true;
if (this.HasEnd && other.IsInRange(this.End))
return true;
return false;
}
public static Interval<T> Merge(Interval<T> int1, Interval<T> int2)
{
if (!int1.Overlaps(int2))
{
throw new ArgumentException("Interval ranges do not overlap.");
}
bool hasStart = false;
bool hasEnd = false;
T start = default(T);
T end = default(T);
if (int1.HasStart && int2.HasStart)
{
hasStart = true;
start = (int1.Start.CompareTo(int2.Start) < 0) ? int1.Start : int2.Start;
}
if (int1.HasEnd && int2.HasEnd)
{
hasEnd = true;
end = (int1.End.CompareTo(int2.End) > 0) ? int1.Start : int2.Start;
}
return CreateInternal(start, hasStart, end, hasEnd);
}
private static Interval<T> CreateInternal(T start, bool hasStart, T end, bool hasEnd)
{
var i = new Interval<T>();
i.Start = start;
i.End = end;
i.HasEnd = hasEnd;
i.HasStart = hasStart;
return i;
}
public static Interval<T> Create(T start, T end)
{
return CreateInternal(start, true, end, true);
}
public static Interval<T> CreateLowerBound(T start)
{
return CreateInternal(start, true, default(T), false);
}
public static Interval<T> CreateUpperBound(T end)
{
return CreateInternal(default(T), false, end, true);
}
public bool IsInRange(T item)
{
if (HasStart && item.CompareTo(Start) < 0)
{
return false;
}
if (HasEnd && item.CompareTo(End) >= 0)
{
return false;
}
return true;
}
}
Included a starting point below.
Though this would be a nice brain teaser, so gave it a try. This is far from complete and a lot more operations could be conjured up, but it's a start.
class Program
{
public static void Main(string[] args)
{
var boundedOpenInterval = Interval<int>.Bounded(0, Edge.Open, 10, Edge.Open);
var boundedClosedInterval = Interval<int>.Bounded(0, Edge.Closed, 10, Edge.Closed);
var smallerInterval = Interval<int>.Bounded(3, Edge.Closed, 7, Edge.Closed);
var leftBoundedOpenInterval = Interval<int>.LeftBounded(10, Edge.Open);
var leftBoundedClosedInterval = Interval<int>.LeftBounded(10, Edge.Closed);
var rightBoundedOpenInterval = Interval<int>.RightBounded(0, Edge.Open);
var rightBoundedClosedInterval = Interval<int>.RightBounded(0, Edge.Closed);
Assert.That(
boundedOpenInterval.Includes(smallerInterval)
);
Assert.That(
boundedOpenInterval.Includes(5)
);
Assert.That(
leftBoundedClosedInterval.Includes(100)
);
Assert.That(
!leftBoundedClosedInterval.Includes(5)
);
Assert.That(
rightBoundedClosedInterval.Includes(-100)
);
Assert.That(
!rightBoundedClosedInterval.Includes(5)
);
}
}
public class Interval<T> where T : struct, IComparable<T>
{
private T? _left;
private T? _right;
private int _edges;
private Interval(T? left, Edge leftEdge, T? right, Edge rightEdge)
{
if (left.HasValue && right.HasValue && left.Value.CompareTo(right.Value) > 0)
throw new ArgumentException("Left edge must be lower than right edge");
_left = left;
_right = right;
_edges = (leftEdge == Edge.Closed ? 0x1 : 0) | (rightEdge == Edge.Closed ? 0x2 : 0);
}
public T? Left
{
get { return _left; }
}
public Edge LeftEdge
{
get { return _left.HasValue ? ((_edges & 0x1) != 0 ? Edge.Closed : Edge.Open) : Edge.Unbounded; }
}
public T? Right
{
get { return _right; }
}
public Edge RightEdge
{
get { return _right.HasValue ? ((_edges & 0x2) != 0 ? Edge.Closed : Edge.Open) : Edge.Unbounded; }
}
public bool Includes(T value)
{
var leftCompare = CompareLeft(value);
var rightCompare = CompareRight(value);
return
(leftCompare == CompareResult.Equals || leftCompare == CompareResult.Inside) &&
(rightCompare == CompareResult.Equals || rightCompare == CompareResult.Inside);
}
public bool Includes(Interval<T> interval)
{
var leftEdge = LeftEdge;
if (leftEdge != Edge.Unbounded)
{
if (
leftEdge == Edge.Open &&
interval.LeftEdge == Edge.Closed &&
interval._left.Equals(_left)
)
return false;
if (interval.CompareLeft(_left.Value) == CompareResult.Inside)
return false;
}
var rightEdge = RightEdge;
if (rightEdge != Edge.Unbounded)
{
if (
rightEdge == Edge.Open &&
interval.RightEdge == Edge.Closed &&
interval._right.Equals(_right)
)
return false;
if (interval.CompareRight(_right.Value) == CompareResult.Inside)
return false;
}
return true;
}
private CompareResult CompareLeft(T value)
{
var leftEdge = LeftEdge;
if (leftEdge == Edge.Unbounded)
return CompareResult.Equals;
if (leftEdge == Edge.Closed && _left.Value.Equals(value))
return CompareResult.Inside;
return _left.Value.CompareTo(value) < 0
? CompareResult.Inside
: CompareResult.Outside;
}
private CompareResult CompareRight(T value)
{
var rightEdge = RightEdge;
if (rightEdge == Edge.Unbounded)
return CompareResult.Equals;
if (rightEdge == Edge.Closed && _right.Value.Equals(value))
return CompareResult.Inside;
return _right.Value.CompareTo(value) > 0
? CompareResult.Inside
: CompareResult.Outside;
}
public static Interval<T> LeftBounded(T left, Edge leftEdge)
{
return new Interval<T>(left, leftEdge, null, Edge.Unbounded);
}
public static Interval<T> RightBounded(T right, Edge rightEdge)
{
return new Interval<T>(null, Edge.Unbounded, right, rightEdge);
}
public static Interval<T> Bounded(T left, Edge leftEdge, T right, Edge rightEdge)
{
return new Interval<T>(left, leftEdge, right, rightEdge);
}
public static Interval<T> Unbounded()
{
return new Interval<T>(null, Edge.Unbounded, null, Edge.Unbounded);
}
public override bool Equals(object obj)
{
if (ReferenceEquals(this, obj))
return true;
var other = obj as Interval<T>;
if (other == null)
return false;
return
((!_left.HasValue && !other._left.HasValue) || _left.Equals(other._left)) &&
((!_right.HasValue && !other._right.HasValue) || _right.Equals(other._right)) &&
_edges == other._edges;
}
public override int GetHashCode()
{
return
(_left.HasValue ? _left.GetHashCode() : 0) ^
(_right.HasValue ? _right.GetHashCode() : 0) ^
_edges.GetHashCode();
}
public static bool operator ==(Interval<T> a, Interval<T> b)
{
return ReferenceEquals(a, b) || a.Equals(b);
}
public static bool operator !=(Interval<T> a, Interval<T> b)
{
return !(a == b);
}
public override string ToString()
{
var leftEdge = LeftEdge;
var rightEdge = RightEdge;
var sb = new StringBuilder();
if (leftEdge == Edge.Unbounded)
{
sb.Append("(-∞");
}
else
{
if (leftEdge == Edge.Open)
sb.Append('(');
else
sb.Append('[');
sb.Append(_left.Value);
}
sb.Append(',');
if (rightEdge == Edge.Unbounded)
{
sb.Append("∞)");
}
else
{
sb.Append(_right.Value);
if (rightEdge == Edge.Open)
sb.Append(')');
else
sb.Append(']');
}
return sb.ToString();
}
private enum CompareResult
{
Inside,
Outside,
Equals
}
}
public enum Edge
{
Open,
Closed,
Unbounded
}
I implemented this a long time ago for the .NET framework, and even included support for DateTime and TimeSpan, as this was one of my main use cases (implementation of a time line in WPF). My implementation supports all you request, except unbounded intervals. This allowed me to do cool stuff like:
// Mockup of a GUI element and mouse position.
var timeBar = new { X = 100, Width = 200 };
int mouseX = 180;
// Find out which date on the time bar the mouse is positioned on,
// assuming it represents whole of 2014.
var timeRepresentation = new Interval<int>( timeBar.X, timeBar.X + timeBar.Width );
DateTime start = new DateTime( 2014, 1, 1 );
DateTime end = new DateTime( 2014, 12, 31 );
var thisYear = new Interval<DateTime, TimeSpan>( start, end );
DateTime hoverOver = timeRepresentation.Map( mouseX, thisYear );
// If the user clicks, zoom in to this position.
double zoomLevel = 0.5;
double zoomInAt = thisYear.GetPercentageFor( hoverOver );
Interval<DateTime, TimeSpan> zoomed = thisYear.Scale( zoomLevel, zoomInAt );
// Iterate over the interval, e.g. draw labels.
zoomed.EveryStepOf( TimeSpan.FromDays( 1 ), d => DrawLabel( d ) );
More recently, I have ported a base AbstractInterval<T> to an early version of .NET standard which simplifies the implementation of concrete types. For example, IntInterval which is included in the library. Due to restrictions (at the time at least) of .NET standard, I had to target .NET Core for a complete generic implementation. A fully generic Interval<T> implementation builds on top of the .NET Standard base classes.
The biggest down side to this is there are quite a few dependencies all over the place (thus copy pasting part of this project will be hard). The reason for this is the implementation of this is not trivial at all (unlike others who have commented on this). In case there still aren't any good 'interval' libraries for .NET I should really make this a separate package. The .NET Standard library is available on Nuget.
Such a thing is trivial to implement. Note that because most primitive datatypes and also DateTime implement IComparable, you can make create a generic inval type which can work with all these types.
I'd generally use the standard .NET Framework classes.
int a = 2;
int b = 10;
// a < x <= b
var interval1 = new HashSet<int>(Enumerable.Range(a + 1, b - a));
// Dump is a LINQPad extension method.
interval1.Dump();
// 3..10
// Check if point in interval
interval1.Contains(a).Dump();
// False
interval1.Contains(b).Dump();
// True
var overlappingInterval = new HashSet<int>(Enumerable.Range(9, 3));
overlappingInterval.Dump();
// 9, 10, 11
var nonOverlappingInterval = new HashSet<int>(Enumerable.Range(11, 2));
nonOverlappingInterval.Dump();
// 11, 12
interval1.Overlaps(overlappingInterval).Dump();
// True
interval1.Overlaps(nonOverlappingInterval).Dump();
// False
interval1.UnionWith(overlappingInterval);
interval1.Dump();
// 3..11
// Alternately use LINQ's Union to avoid mutating.
// Also IntersectWith, IsSubsetOf, etc. (plus all the LINQ extensions).
EDIT: If you want to enforce that this is an interval instead of a set (and/or enforce immutability) you could wrap this in a custom class.
I've found a implementation for DateTimeOffSet only (No numerical) that works fine and have all those methods below. Since this question is top hanked in Google, I'm contributing here:
Covers(t: DateTime) : bool
Join(s: IDisjointIntevalSet) : IDisjointIntevalSet
Join(i: IInterval) : IDisjointIntevalSet
Intersect(i : IInterval) : IDisjointIntevalSet
Consolidate() : IDisjointIntevalSet
Avaliable at GitHub and nuget

C#, Flags Enum, Generic function to look for a flag

I'd like one general purpose function that could be used with any Flags style enum to see if a flag exists.
This doesn't compile, but if anyone has a suggestion, I'd appreciate it.
public static Boolean IsEnumFlagPresent<T>(T value,T lookingForFlag)
where T:enum
{
Boolean result = ((value & lookingForFlag) == lookingForFlag);
return result ;
}
No, you can't do this with C# generics. However, you could do:
public static bool IsEnumFlagPresent<T>(T value, T lookingForFlag)
where T : struct
{
int intValue = (int) (object) value;
int intLookingForFlag = (int) (object) lookingForFlag;
return ((intValue & intLookingForFlag) == intLookingForFlag);
}
This will only work for enums which have an underlying type of int, and it's somewhat inefficient because it boxes the value... but it should work.
You may want to add an execution type check that T is actually an enum type (e.g. typeof(T).BaseType == typeof(Enum))
Here's a complete program demonstrating it working:
using System;
[Flags]
enum Foo
{
A = 1,
B = 2,
C = 4,
D = 8
}
class Test
{
public static Boolean IsEnumFlagPresent<T>(T value, T lookingForFlag)
where T : struct
{
int intValue = (int) (object) value;
int intLookingForFlag = (int) (object) lookingForFlag;
return ((intValue & intLookingForFlag) == intLookingForFlag);
}
static void Main()
{
Console.WriteLine(IsEnumFlagPresent(Foo.B | Foo.C, Foo.A));
Console.WriteLine(IsEnumFlagPresent(Foo.B | Foo.C, Foo.B));
Console.WriteLine(IsEnumFlagPresent(Foo.B | Foo.C, Foo.C));
Console.WriteLine(IsEnumFlagPresent(Foo.B | Foo.C, Foo.D));
}
}
You're looking to replace one line of code with a function that wraps one line of code? I'd say to just use the one line of code...
For what its worth, I recently read that this feature will be part of .NET 4.0. Specifically, it is implemented in the Enum.HasFlag() function.
I have used this before:
public static bool In<T>(this T me, T values)
where T : struct, IConvertible
{
return (me.ToInt64(null) & values.ToInt64(null)) > 0;
}
What I like about it is you can use this clean syntax to call it since in 3.5 the compiler will can infer generic parameters.
AttributeTargets a = AttributeTargets.Class;
if (a.In(AttributeTargets.Class | AttributeTargets.Module))
{
// ...
}
You can do this without generics:
static bool ContainsFlags(Enum value, Enum flag)
{
if (Enum.GetUnderlyingType(value.GetType()) == typeof(ulong))
return (Convert.ToUInt64(value) & Convert.ToUInt64(flag)) == Convert.ToUInt64(flag);
else
return (Convert.ToInt64(value) & Convert.ToInt64(flag)) == Convert.ToInt64(flag);
}
I'm converting to Int64 in this case, which should handle every case except ulong, which is why the extra check...
Why not write an extension method for this? I did this in another post
public static class EnumerationExtensions {
public static bool Has<T>(this System.Enum type, T value) {
try {
return (((int)(object)type & (int)(object)value) == (int)(object)value);
}
catch {
return false;
}
}
//... etc...
}
//Then use it like this
bool hasValue = permissions.Has(PermissionTypes.Delete);
It could use a little refinement (since it assumes everything can be cast as an int), but it could get you started...
Worth pointing out that simply providing some static overloads for all the integral types will work so long as you know you are working with a specific enum. They won't work if the consuming code is likewise operating on where t : struct
If you need to deal with arbitrary (struct) T
You cannot currently do a fast conversion of a generically typed struct into some alternate bitwise form (i.e. roughly speaking a reinterpret_cast) without using C++/CLI
generic <typename T>
where T : value class
public ref struct Reinterpret
{
private:
const static int size = sizeof(T);
public:
static int AsInt(T t)
{
return *((Int32*) (void*) (&t));
}
}
This will then let you write:
static void IsSet<T>(T value, T flags) where T : struct
{
if (!typeof(T).IsEnum)
throw new InvalidOperationException(typeof(T).Name +" is not an enum!");
Type t = Enum.GetUnderlyingType(typeof(T));
if (t == typeof(int))
{
return (Reinterpret.AsInt(value) & Reinterpret.AsInt(flags)) != 0
}
else if (t == typeof(byte))
{
return (Reinterpret.AsByte(value) & Reinterpret.AsByte(flags)) != 0
}
// you get the idea...
}
You cannot constrain to enums. But the mathematical validity of these methods do not change if they are used with non enum types so you could allow them if you can determine that they are convertible to a struct of the relevant size.
Question long over, but here's one for reference anyway:
public static bool HasFlag<TEnum>(this TEnum enumeratedType, TEnum value)
where TEnum : struct, IComparable, IFormattable, IConvertible
{
if (!(enumeratedType is Enum))
{
throw new InvalidOperationException("Struct is not an Enum.");
}
if (typeof(TEnum).GetCustomAttributes(
typeof(FlagsAttribute), false).Length == 0)
{
throw new InvalidOperationException("Enum must use [Flags].");
}
long enumValue = enumeratedType.ToInt64(CultureInfo.InvariantCulture);
long flagValue = value.ToInt64(CultureInfo.InvariantCulture);
if ((enumValue & flagValue) == flagValue)
{
return true;
}
return false;
}
Today, you can set the c# language version to >=7.3
and use the next code as the reference:
public static class EnumExt
{
public static IEnumerable<TEnum> Explode<TEnum>(this TEnum enumValue) where TEnum : Enum
{
var res = Enum.GetValues(enumValue.GetType())
.Cast<TEnum>()
.Where(x => enumValue.HasFlag(x));
return res;
}
public static string ExplodeToString<TEnum>(this TEnum enumValue, string delimeter = ",") where TEnum : Enum
{
return string.Join(delimeter, Explode(enumValue));
}
}
Well, I don't believe there is a way to do this, as there are no constraints that apply to bitwise operators.
However... you can just cast your enum to int and do it.
public static Boolean IsEnumFlagPresent(int value,int lookingForFlag)
{
return ((value & lookingForFlag) == lookingForFlag);
}
This works, but may be confusing to someone.
below is code that benchmarks 4 different methods. results are shown in code in comment "BENCHMARK: .. nSec".
"((enum & flag) != 0)' is 10x faster than HasFlag() function. if you are in a tight loop, then i think it is best to accept it.
public static int jumpCtr=0;
public static int ctr=0;
public static TestFlags gTestFlags = TestFlags.C;
[Flags] public enum TestFlags { A=1<<1, B=1<<2, C=1<<3 }
public static void Jump() { jumpCtr++; gTestFlags = (gTestFlags == TestFlags.B) ? TestFlags.C : TestFlags.B; }
// IsEnumFlagPresent() https://stackoverflow.com/questions/987607/c-flags-enum-generic-function-to-look-for-a-flag
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlag_Faster<T>(T value, T lookingForFlag)
where T : struct
{
int intValue = (int) (object) value;
int intLookingForFlag = (int) (object) lookingForFlag;
return ((intValue & intLookingForFlag) != 0);
}
// IsEnumFlagPresent() https://stackoverflow.com/questions/987607/c-flags-enum-generic-function-to-look-for-a-flag
[MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool HasFlag_Faster_Integer(int intValue, int intLookingForFlag)
{
return ((intValue & intLookingForFlag) != 0);
}
public static void Benchmark_HasFlag( )
{
if ( ! hwDvr._weAreOnGswCpu) { return; }
DateTime timer = DateTime.Now;
string a, b, c, d, e;
double base_nSecPerLoop, b_nSecPerLoop, c_nSecPerLoop, d_nSecPerLoop, e_nSecPerLoop;
int numOfLoops = (int) 1.0e6;
// ------------------------------------------------------
for (int i=0; i<numOfLoops;i++) {
Jump();
}
a = BenchMarkSystem_Helper.SimpleTimer_Loops( ref timer, numOfLoops, out base_nSecPerLoop);
// ------------------------------------------------------
// BENCHMARK: 50 nSec
for (int i=0; i<numOfLoops;i++) {
if (gTestFlags.HasFlag((TestFlags) TestFlags.C)) {
ctr++;
}
Jump();
}
b = BenchMarkSystem_Helper.SimpleTimer_Loops( ref timer, numOfLoops, out b_nSecPerLoop );
double b_diff = b_nSecPerLoop - base_nSecPerLoop;
// ------------------------------------------------------
// BENCHMARK: 3 nSec
for (int i=0; i<numOfLoops;i++) {
if ((gTestFlags & TestFlags.C) != 0) {
ctr++;
}
Jump();
}
c = BenchMarkSystem_Helper.SimpleTimer_Loops( ref timer, numOfLoops, out c_nSecPerLoop );
double c_diff = c_nSecPerLoop - base_nSecPerLoop;
// ------------------------------------------------------
// BENCHMARK: 64 nSec
for (int i=0; i<numOfLoops;i++) {
if (HasFlag_Faster<TestFlags>(value:gTestFlags, lookingForFlag: TestFlags.C)) {
ctr++;
}
Jump();
}
d = BenchMarkSystem_Helper.SimpleTimer_Loops( ref timer, numOfLoops, out d_nSecPerLoop );
double d_diff = d_nSecPerLoop - base_nSecPerLoop;
// ------------------------------------------------------
// BENCHMARK: 14 nSec
for (int i=0; i<numOfLoops;i++) {
if (HasFlag_Faster_Integer((int)gTestFlags, (int)TestFlags.C)) {
ctr++;
}
Jump();
}
e = BenchMarkSystem_Helper.SimpleTimer_Loops( ref timer, numOfLoops, out e_nSecPerLoop );
double e_diff = e_nSecPerLoop - base_nSecPerLoop;
int brkPt=0;
}

Categories

Resources