let's say I have a list of decimals :
List<decimal> values;
and 2 function to display a decimal :
string DisplayPct(decimal pct)
{
return pct.ToString("0.00 %");
}
string DisplayValue(decimal val)
{
return val.ToString("0.00");
}
What would be the best mechanism to implement so I could know which function to call depending on the value?
I would have liked to have for instance typedefs in C#. That way, I could have declared a type Percent and a type Decimal that would both represent decimal values, but then I could know how to display the value based on its type.
Any equivalent in C# ?
Thanks
Here are my classes :
public class Percent
{
public decimal value;
public Percent(decimal d) { value = d; }
public static implicit operator Percent(decimal d) { return new Percent(d); }
public static implicit operator decimal(Percent p) { return p.value; }
}
public class DecimalPrecise
{
public decimal value;
public DecimalPrecise(decimal d) { value = d; }
public static implicit operator DecimalPrecise(decimal d) { return new DecimalPrecise(d); }
public static implicit operator decimal(DecimalPrecise d) { return d.value; }
}
Wrap percent in a class. A bit of work on your part. Just make sure to define the implicit operator to capture decimals, and some of the other operations and ToString as you require.
It sounds like you want two classes: a decimal and a percent. Each one will have a ToString that prints appropriately. If they both have the same interface, you can have a collection of both in a List using that common interface.
Related
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();
}
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>.
For money I am using a custom value type which holds only one decimal field. Simplified code is as follows.
public struct Money
{
private decimal _value;
private Money(decimal money)
{
_value = Math.Round(money, 2, MidpointRounding.AwayFromZero);
}
public static implicit operator Money(decimal money)
{
return new Money(money);
}
public static explicit operator decimal(Money money)
{
return money._value;
}
}
While using this struct in my project sometimes an ambiguity arises. And also sometimes I am setting an object with a constant number which is supposed to be a Money. For now I am initializing the object like,
object myObject=(Money)200;
Can I assign a suffix for my custom type Money. I'd like to initialize the object with the following.
object myObject=200p;
You can't assign custom suffixes with C#. The closest thing you can do is creating extension method for integers:
public static Money Para(this int value) // you can do same for decimals
{
return (Money)((decimal)value);
}
Usage:
var amount = 200.Para();
I need to overload some operators when called using Double types. To achieve this, I'm creating a class MyDouble, which inherits from Double. MyDouble looks somewhat like this
class MyDouble : Double
{
Double value;
// operator overloads go here
}
I want to abstract away the value property from the user so that it is usable just as a Double. Basically I want the user to be able to do this:
MyDouble a = 5; //a.value gets assigned 5
Console.WriteLine(a); //prints a.value
I don't want the user to have to specifically target the value property. Is this possible? How would I go about it?
You can define an implicit conversion operator, like this:
class MyDouble {
public Value {get; private set;}
public Double(double value) {
Value = value;
}
// Other declarations go here...
public static implicit operator double(MyDouble md) {
return md.Value;
}
public static implicit operator MyDouble(double d) {
return new MyDouble(d);
}
}
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);
}