Operators and inheritance - c#

My brain has turned to jelly, or I'm having an out of mind experience, or something. I'm tinkering with a class hierarchy that looks a bit like this:
My Money class looks like this:
public abstract class Money
{
public int Amount { get; set; }
public static bool operator ==(Money leftSide, Money rightSide)
{
// Money can only be equal if it is in the same currency.
if (leftSide.GetType() != rightSide.GetType()) return false;
return leftSide.Amount == rightSide.Amount;
}
public static bool operator !=(Money leftSide, Money rightSide)
{
// If the currencies are different, the amounts are always considered unequal.
if (leftSide.GetType() != rightSide.GetType()) return true;
return leftSide.Amount != rightSide.Amount;
}
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand * multiplier;
return result;
}
public static Dollar Dollar(int amount)
{
return new Dollar(amount);
}
public static Franc Franc(int amount)
{
return new Franc(amount);
}
}
My Dollar operator * looks like this:
public static Dollar operator *(Dollar multiplicand, int multiplier)
{
var result = multiplicand.Amount * multiplier;
return new Dollar(result);
}
Now, if I run this test code, I get a Stack overflow (wahoo!)
{
Money fiveDollars = Money.Dollar(5);
Money timesTwo = fiveDollars*2;
}
I had expected that this would recursively call the subclass (Dollar) operator *, which would return a definite result since (Dollar * int) is defined non-recursively. Since this doesn't work, the alternative is that I have done something dumb. Why doesn't this work? What would be the right way to get this behaviour?

You seem to have left out .Amount
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand.Amount * multiplier;
return result;
}

The problem is that you expect that you can override operators in derived classes and expect dynamic binding. This is not the way it works in C#. Operators are overloaded and the actual overload is chosen compile-time. This means that the following code is recursive and calls itself:
public static Money operator *(Money multiplicand, int multiplier)
{
var result = multiplicand * multiplier;
return result;
}
Another example where you can see the difference between operator overloading and method overriding is this:
int a = 5;
int b = 5;
Console.WriteLine(a == b); // true
Console.WriteLine(a.Equals(b)); // true
Console.WriteLine((object)a == (object)b); // false
Console.WriteLine(((object)a).Equals((object)b)); // true
In the third case, C# treats a and b as objects instead of integers, so it uses the default == operator that is used for objects: comparing references (in this case the references of boxed integers).
This can make it awkward to define operators on a class hierarchy where you want to redefine the operators in derived classes. It is especially awkward when the behavior depends on the combination of both operands, since C# (and most other OOP languages) lacks support for multiple dispatch. You can solve this by using the visitor pattern, but I think in this case you should reconsider if using subclasses for each currency is the best solution.

Related

How to Create Incompatible Number Subtypes

Note: This question is nearly identical to this one. But this one is about C#, not Java.
In Ada, it is possible to create incompatible equivalent numeric types:
type Integer_1 is range 1 .. 10;
type Integer_2 is range 1 .. 10;
A : Integer_1 := 8;
B : Integer_2 := A; -- illegal!
This prevents accidental logical errors such as adding a temperature to a distance.
Is it possible to do something similar in C#? E.g.
class BookId : int {}
class Book
{
BookId Id;
}
class PageId : int {}
class Page
{
PageId Id;
}
class Word
{
BookId BookId;
PageId PageId;
string text;
}
var book = new Book { Id = 1 };
var page = new Page { Id = 1 };
var book = new Word
{
BookId = book.Id, // Ok
PageId = book.Id, // Illegal!
string = "eratosthenes"
};
Yes, you can create types that behave like numeric values but can't be assigned to each other. You can't derive from numeric type, but wrapping one into a struct would be comparable efficient (if that's a concern) or you can add more info (like units). You may be even create generic type if you don't need cross-type operations.
You can see Complex type for full set of operations and interfaces that make type behave very close to regular numbers (including plenty of conversions back and forth as needed).
Some basic class:
class Distance
{
float d;
public Distance(float d)
{
this.d = d;
}
public static Distance operator+(Distance op1, Distance op2)
{
return new Distance(op1.d + op2.d);
}
// ==, !=, Equals and GetHashCode are not required but if you
// need one (i.e. for comparison you need ==, to use values of this
// type in Dictionaries you need GetHashCode)
// you have to implement all
public static bool operator == (Distance op1, Distance op2)
{
return op1.d == op2.d;
}
public static bool operator !=(Distance op1, Distance op2)
{
return op1.d != op2.d;
}
public override bool Equals(object obj)
{
return (object)this == obj || ((obj is Distance) && (obj as Distance)==this);
}
public override int GetHashCode()
{
return d.GetHashCode();
}
// Some basic ToString so we can print it in Console/use in
// String.Format calls
public override string ToString()
{
return $"{d} M";
}
}
Which lets you add values of the same type but will fail to add any other type:
Console.WriteLine(new Distance(1) + new Distance(2)); // "3 M"
// Console.WriteLine(new Distance(1) + 2); // fails to compile
Picking between class and struct for such sample is mostly personal preference, for real usage make sure to know difference between value and reference type before picking one and decide what works for you (struct is likely better for numbers).
More information:
Units of measure in C# - almost - even if you don't go all the way it shows how to make generic numeric type so you can easily create many types without much code (UnitDouble<T> in that post), Arithmetic operator overloading for a generic class in C# - discusses issues you face if you want to go other way and support varying base numeric types (like Distance<float> and Distance<int>).
It turns out my needs were a bit more simple than I thought. What I needed was a unique ID that could not be confused with another unique ID. In the end, I went with a template wrapper for an int.
class Id<T> {
private int id;
public Id(int id) { this.id = id; }
public static implicit operator ID<T>(int value) { return new ID<T>(value); }
public static implicit operator int(ID<T> value) { return value?.id ?? 0; }
public static implicit operator int?(ID<T> value) { return value?.id; }
public static implicit operator ID<T>(int? value)
{
if (value == null) { return null; }
return new ID<T>(value.Value);
}
public override string ToString() { return id.ToString(); }
}
class Book { Id<Book> Id; }
class Page { Id<Page> Id; }
Book.Id cannot be assigned to Page.Id, but either can go back and forth with ints.
I realise now that I've seen this pattern before somewhere, so I guess it's not that original...

C# Operator Overloading, rewriting string?

I'm very fresh to C#
Currently learning Operator overloading
i'm trying to do something like this:
string val = 500; (I can't implicitly)
and then
Number n1 = val;
I manages to get the Number n1 = someintvalue, for instance:
Number n1 = 500;
like this:
public struct Number
{
public int Value { get; set; }
public Number(int Val)
{
Value = Val;
}
public static implicit operator Number(int num)
{
return new Number(num);
}
}
However, when trying to make Number n1 = val; (when val is a string)
I simply cant since the first line cant compile:
string val = 500;
and the following wont work:
public static implicit operator string(int A)
{
return new string(A);
}
because of 1 error which i can not understand
1)User-defined conversion must convert to or from the enclosing type
by the way i get the idea of op overload
underthis specific case of: return new Number(num);
I simply init the ctor
still need some more fundemental understanding
thx ahead!
I presume the function you quote is within the Number class. You have added a conversion operator from an int to a string within that class, which is not legal. You can only add operators that convert to or from the type they're defined in, such as:
public static implicit operator string(Number A)
{
return new string(A.Value);
}
which will fail because string does not have a constructor that takes an int. You could do:
public static implicit operator string(Number A)
{
return A.ToString();
}
But the standard way to "convert" to a string is to overload the ToString method, which the compiler often calls automatically when a conversion to string is requested:
public override string ToString()
{
return Value.ToString();
}

CodeWars C# Kata stumble

"The following code is not executing properly, try to figure out why."
public class CustomMath {
public static int multiply(int a, string b) {
return a * b;
}
}
Here's my solution:
public class CustomMath
{
Int i = 1;
public static int multiply(int a, int b)
{
return a * b;
}
}
I'm still plugging away at it started looking at operator overloading. Still catching the fail so I guess I am still not seeing it or failing to understand something about using operator overloading. Is the operator overloading my only issue or is my return syntax off?
using system;
public class CustomMath
{
public static int operator *(int a, string b)
{
return a * b;
}
}
So I'm looking into binary operators, pretty sure my issue is that I am not expressing the int and string properly.
from the error that you've got you should understand that the function signiture is wrong and you need to change the type of b (string) to be int. so your code would be:
public class CustomMath
{
public static int multiply(int a, int b)
{
return a * b;
}
}
Your operator overload won't work, because in order to overload the multiplication operator, at least one of the operands has to be of a user-defined type.
The thing is, you don't need overloading at all. There are methods in the .NET framework designed specifically to "extract" an integer from a string, which is what you should do before multiplying anything. There are two easy ways of achieving this: int.Parse and int.TryParse. Just take a look at the MSDN documentation to figure out how they work and choose the best in your specific scenario.
And here is int.Parse in action:
string s = "5";
int i = int.Parse(s);
int j = i + 10 // At this point j = 15

Overloading Primitive Operator (C#)

Is there a way I can overload primitives, for example addition with doubles? I want to automatically round the doubles whenever an operation is performed. My current code is this:
class Test{
public static double operator +(double x, double y){
return Math.Round(x + y)
}
}
but there's an unfortunate error that says "One of the parameters of a binary operator must be the containing type".
No, and this would be horrible. Users using your library would suddenly get different behaviors from their double variables!
You can write and use a wrapper object however:
public struct MyDouble
{
public double Value {get; set;}
public MyDouble(double initValue)
{
Value = initValue;
}
public static double operator +(MyDouble x, MyDouble y){
return Math.Round(x.Value + y.Value)
}
}
You can also make it castable to/from a double, among other options. This way users know they are using your object and won't be surprised when their math operations are rounded.
If you want to assign from a simple double, you would need to define an implicit operator, similar to that of Nullable<T> (source):
public static implicit operator MyDouble(double value) {
return new MyDouble(value);
}
You can't overload operators on primitive types. This would cause havoc in your codebase.
What you can do instead, is to create a simple wrapper around the primitive type, let's say RoundedDouble:
public struct RoundedDouble : IEquatable<RoundedDouble>, IComparable<RoundedDouble>
{
public readonly double Value;
public RoundedDouble(double value)
{
Value = Math.Round(value); // Or anything else
}
public static implicit operator RoundedDouble(double value)
{
return new RoundedDouble(value);
}
public static implicit operator double(RoundedDouble wrapper)
{
return wrapper.Value;
}
public int GetHashCode()
{
return Value.GetHashCode();
}
public bool Equals(object other)
{
if (other is RoundedDouble)
return ((RoundedDouble)other).Value == Value;
return false;
}
public string ToString()
{
return Value.ToString();
}
// Add your operators here, and implement the interfaces
}
This is a structure. It has the same value semantics as a double.
Extend it by adding the operators, and by implementing at least IEquatable<RoundedDouble> and IComparable<RoundedDouble>.

How to create a generic C# method that can return either double or decimal?

I have a method like this:
private static double ComputePercentage(ushort level, ushort capacity)
{
double percentage;
if(capacity == 1)
percentage = 1;
// do calculations...
return percentage;
}
Is it possible to make it of a generic type like "type T" where it can return either decimal or double, depending on the type of method expected (or the type put into the function?)
I tried something like this and I couldn't get it to work, because I cannot assign a number like "1" to a generic type. I also tried using the "where T :" after ushort capacity) but I still couldn't figure it out.
private static T ComputePercentage<T>(ushort level, ushort capacity)
{
T percentage;
if(capacity == 1)
percentage = 1; // error here
// do calculations...
return percentage;
}
Is this even possible? I wasn't sure, but I thought this post might suggest that what I'm trying to do is just plain impossible.
EDIT
Thanks to all who responded, many good answers. As Tomas pointed out, this is probably best done in two separate methods. As pointed out by both TreDubZedd and TcKs, the best way to get the functionality I would want is to use an implicit conversion that could return either a double or decimal implicitly.
In fact, you don't need generics but overloading. However you need overloading by return value's type which is supported by IL but is not supported by C#.
I prefere two methods for every return's value type:
static double ComputePercentageDouble (ushort level, ushort capacity)
static decimal ComputePercentageDecimal (ushort level, ushort capacity)
The alternative can be custome type with implicit cast operators:
decimal decimalPercentage = ComputePercentage( 1, 2 );
double doublePercentage = ComputePercentage( 1, 2 );
static DoubleDecimal ComputePercentage( ushort level, ushort capacity ) {
DoubleDecimal percentage = default( DoubleDecimal );
if ( capacity == 1 )
percentage.Number = 1; // error here
// do calculations...
return percentage;
}
public struct DoubleDecimal {
public decimal Number;
public static implicit operator decimal( DoubleDecimal value ) {
return value.Number;
}
public static implicit operator double( DoubleDecimal value ) {
return (double)value.Number;
}
}
You might be able to use implicit conversion: http://msdn.microsoft.com/en-us/library/zk2z37d3.aspx
Generics are useful for writing code that works with any types (perhaps implementing some interface, which can be specified using where). However, if you want to use them for implementing method that can return two different numeric types, it feels a bit wrong (it would work only if double and decimal implemented some shared interface).
You should probably define two distinct methods (e.g. ComputePercentage and ComputePercentagePrecise or something like that - since you can't use overloading using different parameters).
It may be possible to workaround this limitation by using something like this (but that's probably overly complicated for you):
class INumericOps<T> {
public abstract T One { get; }
public abstract T Add(T a, T b);
// and other operations that you may need
}
// Implementations of numeric operations for decimal and double
class DecimalNumerics : INumericOps<decimal> { ... }
class DoubleNumerics : INumericOps<double> { ... }
Then you would write a method that takes INumericOps<T> as a type parameter and uses it to do all mathematics inside the method:
private static R ComputePercentage<T, R>(ushort level, ushort capacity)
where T : INumericOps<R>, where T : new() {
INumericOps<R> ops = new T(); // Get instance with numeric operations
T percentage;
if(capacity == 1)
percentage = ops.One;
// Calculations using ops.Add(.., ..) instead of + etc.
return percentage;
}
Then you would call it like this:
decimal res = ComputePercentage<DecimalNumerics, decimal>(...);
This is a nice trick and it is probably the best (type-safe) workaround you can get. However, it is a bit complicated, so declaring two separate methods may be a better idea.
It's not pretty, but try:
percentage = (T)Convert.ChangeType(1, typeof(T));
This works for both double and decimal at least.
If you're using C# 4.0 you could just return a dynamic.
private static T ComputePercentage<T>(ushort level, ushort capacity)
{
if (typeof(T) == typeof(decimal))
{
decimal percentage = 1;
return (T) (object) percentage;
}
if (typeof(T) == typeof(double))
{
double percentage = 1;
return (T) (object) percentage;
}
throw new NotSupportedExcpetion();
}
Why not create a Percent class?
class Percent
{
public Percent(double value)
{
this.value = value;
}
public double AsDouble()
{
return value;
}
public decimal AsDecimal()
{
return (decimal)value;
}
readonly double value;
}
static Percent ComputePercentage(ushort level, ushort capacity)
{
double percentage = 0;
if (capacity == 1)
{
percentage = 1;
}
// calculations
return new Percent(percentage);
}

Categories

Resources