Im trying to create a ufloat class/struct in c#. It's more of a challenge for me, but would help me control some values in code. After trying a couple of approaches, I finally have one that seems to work:
public struct ufloat
{
public float Value
{
get{ return value; }
set
{
if(value < 0)
{
this.value = 0;
}
else
{
this.value = Math.Abs(value);
}
}
}
}
The problem is, I want it to behave like a typical basic type:
ufloat n = 5;
n += 1;
After some thinking I tried to overload the '=' operator, but it is not possible. Now I am out of ideas. This is why I ask, how can you change this:
ufloat x; x.value = 1;
to this:
ufloat x = 0; x = 1;
?
(Sorry if I am losing something really easy, but I am a self-taught "programmer" and I am pretty new to c#. I learnt c++ at first, and going from lower to higher level isn't easy for me.)
You can't overload the = operator, but you can overload the + operator, and then the += operator (which I believe you meant instead of =+) will work in a reasonably obvious way. You'd also need to add an implicit conversion from float to your struct though.
I would strongly advise not making the struct mutable though - instead, let the + operator return a new value. That will make it behave like every other primitive type, and like most other structs. I'd also rename it to USingle to follow the normal .NET naming conventions (where Single is the CLR name for float). You can't add your own C# alias for a name like float is for Single though.
I suspect your type will want:
A constructor accepting a float
Conversions to and from float (note that normally implicit conversions shouldn't throw exceptions - you may want to ignore that, but I'm not sure...)
Overloads for the arithmetic operators (+, -, * and /)
Overrides of ToString, Equals and GetHashCode
Implementation of IComparable<USingle> and IEquatable<USingle>
You should think about what you want to happen if you add two values which are "large positive floats" together - is the intention that your new type is able to support larger positive values than float can, or is it just "float but always non-negative"?
You can not overload = operator but you may write implicit casts, for example this one is for casting an int:
public class ufloat
{
public float value { get; }
public ufloat(int val) { value = Math.Abs(val); }
public static implicit operator ufloat(int input)
{
return new ufloat(input);
}
}
Now if you assign an int value to it, it will implicitly be converted to ufloat:
ufloat x = -5;
Related
I have a class named FloatPlugIn. I want user to be able to do things like
FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;
float y = 123;
x = y;
That is why I decided to add implicit operator to my class
public static implicit operator FloatPlugIn(float p)
{
return new FloatPlugIn() { Default = p };
}
Problem is that implicit operator has to be static that is why during conversion new instance of my class is created. As a result I am loosing all the information that was located inside of "old" instance.
Is there a way to fix that? I want float value to be applied to existing instance, not to completely replace it.
I don't think you're understanding what conversion does - it's not casting - it must create a new instance. It only makes sense to make it non-static if it were only updating the existing instance.
I think it's better in this case if you either use x.Default = y; or if you create a constructor that takes the float like this:
// Constructor
public FloatPlugIn(float p)
{
Default = p;
}
Usage:
float y = 123;
FloatPlugIn x = new FloatPlugIn(y);
The semantics of the assignment operator requires that behavior. In fact:
The assignment operator (=) stores the value of its right-hand operand in the storage location, property, or indexer denoted by its left-hand operand and returns the value as its result. The operands must be of the same type (or the right-hand operand must be implicitly convertible to the type of the left-hand operand).
It is not the purpose of the implicit conversion operator to modify a destination value—note that there may not be any such destination value, such as in case you pass the value to a parameter of a method.
I want float value to be added to existing instance, not to completely replace it.
If you want an addition (in whatever specific sense that would mean in your case), consider overriding the addition + operator, which in turn has effect on the addition assignment += operator. However, you won't eliminate the creation of a new FloatPlugIn instance anyway.
Consider you'd have the following method in FloatPlugIn, which would modify an existing instance:
public void Add(float f)
{
// do whatever 'addition' means in your case
}
Then the + operator should work like this:
public static FloatPlugIn operator +(FloatPlugIn a, float b)
{
FloatPlugIn result = a.Clone(); // here Clone() denotes any custom method that creates a copy of that instance
result.Add(b);
return b;
}
In your code, the following would work then:
FloatPlugIn x = new FloatPlugIn();
x.Minimum = -100;
x.Maximum = 100;
float y = 123;
x += y; // a new instance is created, but the 'addition' logic is preserved
Also, the same will intuitively work in case of passing a value to a method call:
ProcessMyFloatPlugin(x + 123.0f);
You can see that it is a really good idea to create a new instance of FloatPlugIn as a result of an operator. Otherwise, an in-place modification of x would be, in fact, a nasty side-effect, completely unexpected by any other developer. Note that if performance (avoiding dynamic memory allocations) is a concern, consider using structs.
I know that some people will suggest other ways of performing this same function and I am only interested in specifically accomplishing my goal. I already have working code that performs said task and just would like to understand more about writing my own powerful objects - thank you.
My goal:
int x = 100;
Base b = new Base(0, 3);
b = x; // Preserves my baseNum of 3 for conversions
Code:
public class Base
{
public int count = 0; // represents the count of current numerical value in base ten digit count : 3 -> could be read NEVER user changed
public int baseNum = 10; // conversion base subscript -> """""
public int represented; // represented base ten value of conversion (used for output NOT mathmatically friendly) -> should be read BUT never change by user
public int numerical = 0;
public int[] basearray; // should NOT be modified read only
public Base()
{
//count = 0; // setting numerical will run digit count
baseNum = 10;
numerical = 0;
}
public Base(int i)
{
baseNum = 10;
numerical = i;
}
public Base(int n, int b)
{
baseNum = b;
numerical = n;
}
public static implicit operator Base(int i)
{
// Help needed
}
public static implicit operator int(Base b)
{
int i = b.numerical;
return i;
}
}
I have excluded much of the irrelevant code. This object holds a numerical value but provides a digit by digit reference to a converted format (as we count in base ten this object converts into other base forms)
What I wish is to preserve the current baseNum member and only update the numerical value of my object when using assignment.
As implicit conversion is a static function as far as I know there is no way to access the instance that will be used when assignments are performed after int is casted into my object.
Is there any way to perform this assignment operation in the way I wish?
Again - I already have many methods that allow me to modify the numerical member of the instance.
I also know that I can simply define the baseNum again after assignment.
I only wish to find out if there is a way to possibly utilize my object in the way I am imagining.
You simply can't do that.
When you write b = x, things happen under the hood are:
take the value if x
invoke implicit operator Base(int i) on the value of x, a Base object is returned
assign the returned object to b
There is no conventional way you can access the original value of b in step 2, where the conversion happens.
Is there any way to perform this assignment operation in the way I wish?
No, there is not. Conversion operators, implicit or explicit, always return a new object. And in the case of your reference type, the value returned is a reference, and the assignment is to variable holding that reference, which does not in any way modify the object that variable previously referred to.
Furthermore, I would suggest you should not want to do this anyway. An assignment that only modifies the target partially would be very confusing to anyone reading the code. At first, maybe just confusing to people unfamiliar with the design, but eventually, once the code's been sitting there for awhile without any need to work on it, even people who were theoretically well-versed in the design will have trouble remembering that it does this.
Stick with what you already have, where modification of individual components of an object are expressed explicitly. This will keep the code expressive, simple, and easy to understand.
I'm working on a custom implementation of a Number struct, with very different ways of storing and manipulating numeric values.
The struct is fully immutable - all fields are implemented as readonly
I'm trying to implement the ++ and -- operators, and I've run into a little confusion:
How do you perform the assignment?
Or does the platform handle this automatically, and I just need to return n + 1?
public struct Number
{
// ...
// ... readonly fields and properties ...
// ... other implementations ...
// ...
// Empty placeholder + operator, since the actual method of addition is not important.
public static Number operator +(Number n, int value)
{
// Perform addition and return sum
// The Number struct is immutable, so this technically returns a new Number value.
}
// ERROR here: "ref and out are not valid in this context"
public static Number operator ++(ref Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n = n + 1;
return n;
}
}
EDIT: I think this is not a duplicate of other questions about increment and decrement operators, since this involves value-types which behave differently than classes in this context. I understand similar rules apply regarding ++ and --, but I believe the context of this question is different enough, and nuanced enough, to stand on its own.
The struct is fully immutable - all fields are implemented as readonly
Good!
I'm trying to implement the ++ and -- operators, and I've run into a little confusion: How do you perform the assignment?
You don't. Remember what the ++ operator does. Whether it is prefix or postfix it:
fetches the original value of the operand
computes the value of the successor
stores the successor
produces either the original value or the successor
The only part of that process that the C# compiler does not know how to do for your type is "compute the successor", so that's what your overridden ++ operator should do. Just return the successor; let the compiler deal with figuring out how to make the assignment.
Or does the platform handle this automatically, and I just need to return n + 1?
Yes, do that.
The processing of ++ and -- operators is described in C# language specification, section 7.7.5 Prefix increment and decrement operators:
The run-time processing of a prefix increment or decrement operation of the form ++x or --x consists of the following steps:
• If x is classified as a variable:
o x is evaluated to produce the variable.
o The selected operator is invoked with the value of x as its argument.
o The value returned by the operator is stored in the location given by the evaluation of x.
o The value returned by the operator becomes the result of the operation.
So a custom overloads of these operators only need to produce an incremented/decremented value. The rest is handled by the compiler.
A Number class is going to have a value of some kind as a property.
public static Number operator ++(Number n)
{
// ref seems to be required,
// otherwise this assignment doesn't affect the original variable?
n.value = n.value + 1;
return n;
}
This should do what you want.
I wrote this using your struc and added the value property.
private static void Main(string[] args)
{
var x = new Number();
x.value = 3;
x++;
Console.WriteLine(x.value);
Console.Read();
}
This properly generates a 4
The statement num++; by itself expands to num = PlusPlusOperator(num);. Since your data type is immutable, just return n+1; and the compiler will handle the rest.
I would like to create a generic method which performs basic mathematical operations. For eg. If a double is passed to the function, it will return double.
public static T Multiply<T> (T A, int B)
{
//some calculation here
return (T) A * B;
}
This doesn't work for me.
EDIT: I get an error Operator '*' cannot be applied to operands of type 'T' and 'int'
However I am wondering if there are other ways to achieve what I am trying to?
Thanks
You can do it by constructing and compiling a LINQ expression for the specific type, like this:
private static IDictionary<Type,object> MultByType = new Dictionary<Type,object>();
public static T Multiply<T>(T a, int b) {
Func<T,int,T> mult;
object tmp;
if (!MultByType.TryGetValue(typeof (T), out tmp)) {
var lhs = Expression.Parameter(typeof(T));
var rhs = Expression.Parameter(typeof(int));
mult = (Func<T,int,T>) Expression.Lambda(
Expression.Multiply(lhs, Expression.Convert(rhs, typeof(T)))
, lhs
, rhs
).Compile();
MultByType.Add(typeof(T), mult);
} else {
mult = (Func<T,int,T>)tmp;
}
return mult(a, b);
}
To avoid recompiling the expression each time it is used, one could cache it in a dictionary.
Note that this approach has certain limitations:
Multiplication of T by T is expected to be defined,
The output of multiplication is expected to be T without conversion. This is not true for types smaller than int,
The type must support conversion from int.
None of this is checked at compile time.
This is the simplest to implement, but is not efficient:
public static T Multiply<T>(T A, int B)
{
T val = default(T);
try
{
val = (dynamic)A * B;
}
catch
{ }
return val;
}
Depending on your needs it might be fine for you. You may consider not handling the exception in the method, or using an out value so that you can return both the answer and a success value.
Being stuck on an on older .Net version, without access to dynamic, I have a very simple class that does very much what you're looking for, and allows for use of actual operators: Numeric It may be worth a look on current .Net as well.
Method declaration:
public static T LerpMinMax<T>(Numeric<T> input, Numeric<T> inputMin, Numeric<T> inputMax, Numeric<T> outputMin, Numeric<T> outputMax)
{
if (input <= inputMin)
{
return outputMin;
}
else if (input >= inputMax)
{
return outputMax;
}
return outputMin + ((input - inputMin) / (inputMax - inputMin)) * (outputMax - outputMin);
}
And then use:
float lerp = LerpMinMax<float>(0.55f, 0.0f, 0.1f, 0.0f, 1000.0f);
It's definitely not as flexible as MiscUtil's Operator, but was intended to be simple and (relatively) fast. It's still significantly slower than using operations directly (say by using T4 templates that spit out non-generic type-specific implementations) but used in the above way it's equivalent to MiscUtil's Operator class. It also obviously has the benefit of generally more readable algorithm implementations, and can support custom classes that implement operators.
You should add Dynamic in front of the A
and the conversion to T must be done on the full calculation
public static T Multiply<T>(T A, int B)
{
return (T)((dynamic)A * B);
}
Here's my example for using generics to compare to numbers:
public bool TIsEqual<T>(T f1, T f2, T margin)
{
T diff = default(T);
T error = default(T);
diff = Math.Abs((dynamic)f1 - f2);
error = (dynamic)margin * f1;
return (dynamic) diff < error;
}
Motivation:
In reading Mark Seemann’s blog on Code Smell: Automatic Property he says near the end:
The bottom line is that automatic properties are rarely appropriate.
In fact, they are only appropriate when the type of the property is a
value type and all conceivable values are allowed.
He gives int Temperature as an example of a bad smell and suggests the best fix is unit specific value type like Celsius. So I decided to try writing a custom Celsius value type that encapsulates all the bounds checking and type conversion logic as an exercise in being more SOLID.
Basic requirements:
Impossible to have an invalid value
Encapsulates conversion operations
Effient coping (equivalent to the int its replacing)
As intuitive to use as possible (trying for the semantics of an int)
Implementation:
[System.Diagnostics.DebuggerDisplay("{m_value}")]
public struct Celsius // : IComparable, IFormattable, etc...
{
private int m_value;
public static readonly Celsius MinValue = new Celsius() { m_value = -273 }; // absolute zero
public static readonly Celsius MaxValue = new Celsius() { m_value = int.MaxValue };
private Celsius(int temp)
{
if (temp < Celsius.MinValue)
throw new ArgumentOutOfRangeException("temp", "Value cannot be less then Celsius.MinValue (absolute zero)");
if (temp > Celsius.MaxValue)
throw new ArgumentOutOfRangeException("temp", "Value cannot be more then Celsius.MaxValue");
m_value = temp;
}
public static implicit operator Celsius(int temp)
{
return new Celsius(temp);
}
public static implicit operator int(Celsius c)
{
return c.m_value;
}
// operators for other numeric types...
public override string ToString()
{
return m_value.ToString();
}
// override Equals, HashCode, etc...
}
Tests:
[TestClass]
public class TestCelsius
{
[TestMethod]
public void QuickTest()
{
Celsius c = 41;
Celsius c2 = c;
int temp = c2;
Assert.AreEqual(41, temp);
Assert.AreEqual("41", c.ToString());
}
[TestMethod]
public void OutOfRangeTest()
{
try
{
Celsius c = -300;
Assert.Fail("Should not be able to assign -300");
}
catch (ArgumentOutOfRangeException)
{
// pass
}
catch (Exception)
{
Assert.Fail("Threw wrong exception");
}
}
}
Questions:
Is there a way to make MinValue/MaxValue const instead of readonly? Looking at the BCL I like how the meta data definition of int clearly states MaxValue and MinValue as compile time constants. How can I mimic that? I don’t see a way to create a Celsius object without either calling the constructor or exposing the implementation detail that Celsius stores an int.
Am I missing any usability features?
Is there a better pattern for creating a custom single field value type?
Is there a way to make MinValue/MaxValue const instead of readonly?
No. However, the BCL doesn't do this, either. For example, DateTime.MinValue is static readonly. Your current approach, for MinValue and MaxValue is appropriate.
As for your other two questions - usability and the pattern itself.
Personally, I would avoid the automatic conversions (implicit conversion operators) for a "temperature" type like this. A temperature is not an integer value (in fact, if you were going to do this, I would argue that it should be floating point - 93.2 degrees C is perfectly valid.) Treating a temperature as an integer, and especially treating any integer value implicitly as a temperature seems inappropriate and a potential cause of bugs.
I find that structs with implicit conversion often cause more usability problems than they address. Forcing a user to write:
Celsius c = new Celcius(41);
Is not really much more difficult than implicitly converting from an integer. It is far more clear, however.
I think from a usability point of view I would opt for a type Temperature rather than Celsius. Celsius is just a unit of measure while a Temperature would represent an actual measurement. Then your type could support multiple units like Celsius, Fahrenheit and Kelvin. I would also opt for decimal as backing storage.
Something along these lines:
public struct Temperature
{
private decimal m_value;
private const decimal CelsiusToKelvinOffset = 273.15m;
public static readonly Temperature MinValue = Temperature.FromKelvin(0);
public static readonly Temperature MaxValue = Temperature.FromKelvin(Decimal.MaxValue);
public decimal Celsius
{
get { return m_value - CelsiusToKelvinOffset; }
}
public decimal Kelvin
{
get { return m_value; }
}
private Temperature(decimal temp)
{
if (temp < Temperature.MinValue.Kelvin)
throw new ArgumentOutOfRangeException("temp", "Value {0} is less than Temperature.MinValue ({1})", temp, Temperature.MinValue);
if (temp > Temperature.MaxValue.Kelvin)
throw new ArgumentOutOfRangeException("temp", "Value {0} is greater than Temperature.MaxValue ({1})", temp, Temperature.MaxValue);
m_value = temp;
}
public static Temperature FromKelvin(decimal temp)
{
return new Temperature(temp);
}
public static Temperature FromCelsius(decimal temp)
{
return new Temperature(temp + CelsiusToKelvinOffset);
}
....
}
I would avoid the implicit conversion as Reed states it makes things less obvious. However I would overload operators (<, >, ==, +, -, *, /) as in this case it would make sense to perform these kind of operations. And who knows, in some future version of .net we might even be able to specify operator constraints and finally be able to write more reusable data structures (imagine a statistics class which can calculate statistics for any type which supports +, -, *, /).
DebuggerDisplay is useful touch. I'd add unit of measurements "{m_value} C" so you can immediately see the type.
Depending on target usage you may also want to have generic conversion framework to/from base units in addtion to concrete classes. I.e. store values in SI units, but be able to display/edit based on culture like (degrees C, km, kg) vs. (degrees F, mi, lb).
You may also check out F# measurement units for additioanl ideas ( http://msdn.microsoft.com/en-us/library/dd233243.aspx ) - note that it is compile time construct.
I think this is a perfectly fine implementation pattern for value types. I've done similar things in the past that have worked out well.
Just one thing, since Celsius is implicitly convertible to/from int anyway, you can define the bounds like this:
public const int MinValue = -273;
public const int MaxValue = int.MaxValue;
However, in reality there's no practical difference between static readonly and const.