I want to do a struct for boundedElements like number that has a max and min value. However I'm stuck on how to do this. Here is an example of a property. The setfield method is just a method to set a property and raise a property changed event.
private BoundedComponent<int> nbOfItems = new BoundedComponent<int> (1, int.MaxValue);
public int NbOfItems
{
get => nbOfItems ;
set => SetField(ref nbOfItems, value);
}
protected bool SetField<T>(
ref T field,
T value,
[CallerMemberName]
string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value))
return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
and here is my struct
public struct BoundedComponent<T> where T : struct, IComparable<T>
{
private T value;
private T minValue;
private T maxValue;
public BoundedComponent(T minValue, T maxValue)
{
this.minValue = minValue;
this.maxValue = maxValue;
value = minValue;
}
public static implicit operator T(BoundedComponent<T> d)
{
return d.value;
}
public static implicit operator BoundedComponent<T>(T val)
{
value = BoundValue(val);
}
private T BoundValue(T value)
{
return value.CompareTo(maxValue) > 0 ? maxValue
: value.CompareTo(minValue) < 0 ? minValue : value;
}
}
However I cannot do that because the implicit operator is a static method so I don't have access to the min and max values of the bounded element I want to check.
How can I do such a thing ?
I tried the above method and also using a class with a property Value however I cannot use it inside my setfield method since properties cant be passed by reference.
BoundedComponent
should not have a conversion from T
. An instance of T
simply does not have enough information to create an instance of BoundedComponent
. Namely, T
does not have any information about its minimum and maximum values.
I would make the BoundValue
method actually set value
, and rename it to Set
.
public struct BoundedComponent<T> where T : struct, IComparable<T>
{
private T value;
// consider making these readonly
private readonly T minValue;
private readonly T maxValue;
public BoundedComponent(T minValue, T maxValue)
{
this.minValue = minValue;
this.maxValue = maxValue;
value = minValue;
}
public static implicit operator T(BoundedComponent<T> d)
{
return d.value;
}
public void Set(T value)
{
this.value = value.CompareTo(maxValue) > 0 ? maxValue
: value.CompareTo(minValue) < 0 ? minValue : value;
}
}
You should create a new SetField
method for setting BoundedComponent
s. As you found out, you cannot use the existing SetField
.
Even if you could, the existing SetField
's logic is incorrect for BoundedComponent
s. Suppose the call SetField(ref nbOfItems, -1)
actually works - if nbOfItems
was initially 1
, this would have unexpectedly raised OnPropertyChanged
event.
You should record the old value, try to call Set
, and compare the old value with the current value to see if it changed:
protected bool SetField<T>(
ref BoundedComponent<T> field,
T value,
[CallerMemberName]
string propertyName = null)
where T: struct, IComparable<T>
{
T old = field;
field.Set(value);
if (EqualityComparer<T>.Default.Equals(old, field))
return false;
OnPropertyChanged(propertyName);
return true;
}