How to generate constant values with generic math - c#

I have the following generic math function:
private static T Fade<T>(T t)
where T : IFloatingPoint<T>
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
This doesn't compile however, since 6, 15 and 10 are not of type T.
The best solution I could come up with was to define a static class like this:
private static class GenericValues<T>
where T : IFloatingPoint<T>
{
public static readonly T Two = T.One + T.One;
public static readonly T Three = Two + T.One;
public static readonly T Four = Three + T.One;
public static readonly T Five = Four + T.One;
public static readonly T Six = Five + T.One;
public static readonly T Ten = Two * Three;
public static readonly T Fifteen = Five * Three;
}
And then the function becomes this:
private static T Fade<T>(T t)
where T : IFloatingPoint<T>
{
return t * t * t * (t * (t * GenericValues<T>.Six - GenericValues<T>.Fifteen) + GenericValues<T>.Ten);
}
This feels a bit like a hack though, is there a nicer way to do this?

You can use one of the INumberBase<T>.CreateX methods, for example INumberBase<TSelf>.CreateChecked<TOther>(TOther) to convert the number literals to the generic number type:
private static T Fade<T>(T t)
where T : IFloatingPoint<T>
{
return t * t * t *
(t * (t * T.CreateChecked(6) - T.CreateChecked(15)) + T.CreateChecked(10));
}

Related

c#: define an implicit conversion on a property {get; set} for class

I would like to create a class type that seems to be a double value but adds some functionality to it.
I know the possibility described here. But this does not allow to assign a value to an existing instance:
public interface IUnit
{
double ToScaled(double v);
double ToSI(double v);
}
public class ScalableNumber
{
public IUnit Unit { get; set; }
double val;
public double SI { get => val; set => val = value; }
public double Scaled { get => Unit?.ToScaled(val)??val; set => val = (Unit == null)? value : Unit.ToSI(value); }
public ScalableNumber(IUnit u)
{
Unit = u;
}
// implicit conversion to double, operates like an implicit get
public static implicit operator double(ScalableNumber x) => x.val;
// how do I implement an implicit set, assignig double to val
// implicit constructor from double is not useful because I lose the unit
public static implicit operator ScalableNumber(double x) => new ScalableNumber(null) { val=x};
// implicit array property is not useful because the implicit value is a single value
public double this[int i] { get => val; set => val = value; }
}
public class Unit:IUnit
{
public double scale = 1;
public double ToScaled(double v) => v/scale;
public double ToSI(double v) => scale * v;
}
public class MyExample
{
IUnit kilometer, hour, angstroemPerWeek;
public ScalableNumber way;
public ScalableNumber time;
public ScalableNumber speed;
public MyExample()
{
kilometer = new Unit() { scale = 1000 };
hour = new Unit() { scale = 3600 };
angstroemPerWeek = new Unit() { scale = 1e-10 / (60 * 60 * 24 * 7) };
way = new ScalableNumber(kilometer);
time = new ScalableNumber(hour);
speed = new ScalableNumber(angstroemPerWeek);
}
public static void ExecuteMyExample()
{
var myExample = new MyExample();
myExample.way.Scaled = 100;
myExample.time.Scaled = 1;
Console.WriteLine(myExample.Speed);
}
public void Calculate()
{
//I would like to have speed in Ångström per week.
//What I get with the present implementation is the speed in meters per second (unscaled)
speed = way / time;
}
public string Speed { get { if (time <= 0) return string.Empty; Calculate(); return speed.Scaled.ToString(); } }
}
Of course, I can code in Calculate():
speed.SI = way / time;
But if I could use the assignment without the .SI, I could re-use a lot of methods that are currently programmed for properties that have the type double.
Is there a way in c# to direct an assignment to a property without adding the property name?
The short answer is that you can't overload the assignment operator.
The long answer is that if you're willing to do something a bit hacky, you can kinda accomplish what you want with generics and an upcoming feature of C# 11, static abstract interface members.
Basically if you wanna keep the unit information, you will have to find somewhere else to store it, so store it in the type itself.
public interface IUnit
{
static abstract double ToScaled(double v);
static abstract double ToSI(double v);
}
// these interfaces exist so you can box the struct or use them as a generic constraint
public interface IScalableNumber
{
double SI { get; set; }
double Scaled { get; set; }
}
public interface IScalableNumber<TSelf>
:
IScalableNumber,
IAdditionOperators<TSelf, double, TSelf>
// more I...Operators interfaces
where TSelf : IScalableNumber<TSelf>
{
static abstract implicit operator TSelf(double x);
}
// changed this to struct because I didn't see a reason for it to remain a class
public struct ScalableNumber<TUnit> : IScalableNumber<ScalableNumber<TUnit>> where TUnit : IUnit
{
private double val;
public double SI { get => val; set => val = value; }
public double Scaled { get => TUnit.ToScaled(val); set => TUnit.ToSI(val); }
public static ScalableNumber<TUnit> operator +(ScalableNumber<TUnit> left, double right) => left.val + right;
public static implicit operator double(ScalableNumber<TUnit> x) => x.val;
public static implicit operator ScalableNumber<TUnit>(double x) => new() { val = x };
public ScalableNumber<TNewUnit> WithDifferentUnit<TNewUnit>() where TNewUnit : IUnit => val;
}
public abstract class KilometerUnit : IUnit
{
private const double scale = 1000;
public static double ToScaled(double v) => v / scale;
public static double ToSI(double v) => scale * v;
}
public abstract class HourUnit : IUnit
{
private const double scale = 3600;
public static double ToScaled(double v) => v / scale;
public static double ToSI(double v) => scale * v;
}
public abstract class AngstroemPerWeekUnit : IUnit
{
private const double scale = 1e-10 / (60 * 60 * 24 * 7);
public static double ToScaled(double v) => v / scale;
public static double ToSI(double v) => scale * v;
}
public class MyExample
{
public ScalableNumber<KilometerUnit> way;
public ScalableNumber<HourUnit> time;
public ScalableNumber<AngstroemPerWeekUnit> speed;
public MyExample()
{
way = new();
time = new();
speed = new();
}
public static void ExecuteMyExample()
{
var myExample = new MyExample();
myExample.way.Scaled = 100;
myExample.time.Scaled = 1;
Console.WriteLine(myExample.Speed);
}
public void Calculate()
{
speed = way / time;
//now after the assignment, speed is still in 'AngstroemPerWeek'
// in order to change between units do this
way = time.WithDifferentUnit<KilometerUnit>();
// implicit assignment won't work with the non generic interface:
IScalableNumber speedBoxed = speed;
speedBoxed = 10.0;
// all of these should work flawlessly though :) ... and allocate no heap memory
IncrementScalable(ref way);
IncrementScalable(ref time);
IncrementScalable(ref speed);
}
public void IncrementScalable<TScalable>(ref TScalable someNumber) where TScalable : IScalableNumber<TScalable>
{
someNumber += 1;
}
public string Speed { get { if (time <= 0) return string.Empty; Calculate(); return speed.Scaled.ToString(); } }
}

How to convert - into + to create a conjugate of imaginary part?

I'm trying to overload a / (divide) operator to divide two complex numbers. How do I invert the polarity of imaginary part in a complex number such that it acts a conjugate of complex number hence the distributive multiplication of the complex number and its conjugate can be carried out.
For example:
Dividing these two complex numbers:
(6 + 3i) / (7 - 5i)
[(6 + 3i)*(7 + 5i)] / [(7 - 5i)*(7 + 5i)] //have to create conjugate by inverting signs
7(6 + 3i) + 5i(6 + 3i) / 7(7 - 5i) + 5i(7 + 5i)
Where i² = -1
(42 + 51i + 15) / (49 + 25)
(27 + 5i) / (74) => (27/74) + (51i/74)
My current code is this and is not yielding correct results
rhscomplexnumber stands for right hand side complex number (6 + 3i)
lhscomplexnumber stands for left hand side complex number (7 - 5i)
I am multiplying the -ve imaginary part of rhscomplexnumber with -1 to generate a +ve conjugate of same magnitude.
public class Complex
{
public double Real { get; set; }
public double Imaginary { get; set; }
public override string ToString()
{
if (Real > 0)
return Real.ToString() + "+i" + Imaginary.ToString();
else
return Real.ToString() + "-i" + Math.Abs(Imaginary).ToString();
}
public static Complex operator / (Complex lhscomplexnumber, Complex rhscomplexnumber)
{
Complex result = new Complex();
double NumeratorReal = (rhscomplexnumber.Real * lhscomplexnumber.Real) + (-1*((-1 * rhscomplexnumber.Imaginary) * (lhscomplexnumber.Imaginary)));
double NumeratorImag = (rhscomplexnumber.Real * lhscomplexnumber.Imaginary) + ((-1 * rhscomplexnumber.Imaginary) * (lhscomplexnumber.Real));
double DenominatorReal = (rhscomplexnumber.Real * lhscomplexnumber.Real) + (-1*((-1 * rhscomplexnumber.Imaginary) * (lhscomplexnumber.Imaginary)));
double DenominatorImag = (rhscomplexnumber.Real * lhscomplexnumber.Imaginary) + (-1 * rhscomplexnumber.Imaginary * lhscomplexnumber.Real);
result.Real = NumeratorReal / DenominatorReal;
result.Real = Math.Round(result.Real, 1);
result.Imaginary = NumeratorImag / DenominatorReal;
result.Imaginary = Math.Round(result.Imaginary, 1);
return result;
}
}
Here you go:
public class Complex
{
public double Real { get; set; }
public double Imaginary { get; set; }
public static Complex operator *(Complex a, Complex b) =>
new Complex()
{
Real = a.Real * b.Real - a.Imaginary * b.Imaginary,
Imaginary = a.Real * b.Imaginary + a.Imaginary * b.Real,
};
public static Complex Conjugate(Complex a) =>
new Complex() { Real = a.Real, Imaginary = -a.Imaginary };
public static Complex operator /(Complex a, double b) =>
new Complex() { Real = a.Real / b, Imaginary = a.Imaginary / b };
public static Complex operator /(Complex a, Complex b) =>
a * Conjugate(b) / (b * Conjugate(b)).Real;
}
If you want to go for bonus points, try this:
public struct Complex : IEquatable<Complex>
{
public double R { get; private set; }
public double I { get; private set; }
public static Complex Create(double r, double i) => new Complex() { R = r, I = i };
public static Complex operator +(Complex a, Complex b) => Complex.Create(a.R + b.R, a.I + b.I);
public static Complex operator -(Complex a, Complex b) => Complex.Create(a.R - b.R, a.I - b.I);
public static Complex operator *(Complex a, Complex b) => Complex.Create(a.R * b.R - a.I * b.I, a.R * b.I + a.I * b.R);
public static Complex operator /(Complex a, Complex b) => a * b.Conjugate() / (b * b.Conjugate()).R;
public static Complex operator /(Complex a, double b) => Complex.Create(a.R / b, a.I / b);
public override bool Equals(object obj)
{
if (obj is Complex)
return Equals((Complex)obj);
return false;
}
public bool Equals(Complex obj)
{
if (obj == null) return false;
if (!EqualityComparer<double>.Default.Equals(R, obj.R)) return false;
if (!EqualityComparer<double>.Default.Equals(I, obj.I)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<double>.Default.GetHashCode(R);
hash ^= EqualityComparer<double>.Default.GetHashCode(I);
return hash;
}
public override string ToString()
{
return $"{R}{(I >= 0 ? "+" : "")}{I}";
}
public static bool operator ==(Complex left, Complex right)
{
if (object.ReferenceEquals(left, null))
{
return object.ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static bool operator !=(Complex left, Complex right)
{
return !(left == right);
}
}
public static class ComplexEx
{
public static Complex Conjugate(this Complex a) => Complex.Create(a.R, -a.I);
}

No precision loss integer arithmetic

How would i create a type that works with integers, supports at least addition substraction division and multiplication and guarantees and integer number IF the operation leads to an integer (otherwise throw).
For example i'd like to be able to do something like:
Precise A = 10;
A.Divide(3);
A.GetNumber(); // This would throw an exception as 10/3 isn't an int.
A.Multiply(6);
int result = A.GetNumber; // I want result to be = to 20, not to a floating point type that would round to 2 or be very close like 1.9999999999999999999999998992
I realise this is a odd use case but i do have this need (performing a sequence of operations, which in floating point could be missrepresented, but are guaranteed to end up as a valid int).
Because we can't know that 10 / 3 will eventually result in a precise integer answer until after the * 6 we have to defer it until then with a promise:
public sealed class Precise
{
private interface IOperation
{
int Calculate(int value);
IOperation Combine(IOperation next);
}
private sealed class NoOp : IOperation
{
public static NoOp Instance = new NoOp();
public int Calculate(int value)
{
return value;
}
public IOperation Combine(IOperation next)
{
return next;
}
}
private sealed class Combo : IOperation
{
private readonly IOperation _first;
private readonly IOperation _second;
public Combo(IOperation first, IOperation second)
{
_first = first;
_second = second;
}
public int Calculate(int value)
{
return _second.Calculate(_first.Calculate(value));
}
public IOperation Combine(IOperation next)
{
return new Combo(_first, _second.Combine(next));
}
}
private sealed class Mult : IOperation
{
private readonly int _multiplicand;
public Mult(int multiplicand)
{
_multiplicand = multiplicand;
}
public int Calculate(int value)
{
return value * _multiplicand;
}
public int Multiplicand
{
get { return _multiplicand; }
}
public IOperation Combine(IOperation next)
{
var nextMult = next as Mult;
if(nextMult != null)
return new Mult(_multiplicand * nextMult._multiplicand);
var nextDiv = next as Div;
if(nextDiv != null)
{
int divisor = nextDiv.Divisor;
if(divisor == _multiplicand)
return NoOp.Instance;//multiplcation by 1
if(divisor > _multiplicand)
{
if(divisor % _multiplicand == 0)
return new Div(divisor / _multiplicand);
}
if(_multiplicand % divisor == 0)
return new Mult(_multiplicand / divisor);
}
return new Combo(this, next);
}
}
private sealed class Div : IOperation
{
private readonly int _divisor;
public Div(int divisor)
{
_divisor = divisor;
}
public int Divisor
{
get { return _divisor; }
}
public int Calculate(int value)
{
int ret = value / _divisor;
if(value != ret * _divisor)
throw new InvalidOperationException("Imprecise division");
return ret;
}
public IOperation Combine(IOperation next)
{
var nextDiv = next as Div;
if(nextDiv != null)
return new Div(_divisor * nextDiv._divisor);
var nextMult = next as Mult;
if(nextMult != null)
{
var multiplicand = nextMult.Multiplicand;
if(multiplicand == _divisor)
return NoOp.Instance;
if(multiplicand > _divisor)
{
if(multiplicand % _divisor == 0)
return new Mult(multiplicand / _divisor);
}
else if(_divisor % multiplicand == 0)
return new Div(multiplicand / _divisor);
}
return new Combo(this, next);
}
}
private sealed class Plus : IOperation
{
private readonly int _addend;
public Plus(int addend)
{
_addend = addend;
}
public int Calculate(int value)
{
return value + _addend;
}
public IOperation Combine(IOperation next)
{
var nextPlus = next as Plus;
if(nextPlus != null)
{
int newAdd = _addend + nextPlus._addend;
return newAdd == 0 ? (IOperation)NoOp.Instance : new Plus(newAdd);
}
return new Combo(this, next);
}
}
private readonly int _value;
private readonly IOperation _operation;
public static readonly Precise Zero = new Precise(0);
private Precise(int value, IOperation operation)
{
_value = value;
_operation = operation;
}
public Precise(int value)
: this(value, NoOp.Instance)
{
}
public int GetNumber()
{
return _operation.Calculate(_value);
}
public static explicit operator int(Precise value)
{
return value.GetNumber();
}
public static implicit operator Precise(int value)
{
return new Precise(value);
}
public override string ToString()
{
return GetNumber().ToString();
}
public Precise Multiply(int multiplicand)
{
if(multiplicand == 0)
return Zero;
return new Precise(_value, _operation.Combine(new Mult(multiplicand)));
}
public static Precise operator * (Precise precise, int value)
{
return precise.Multiply(value);
}
public Precise Divide(int divisor)
{
return new Precise(_value, _operation.Combine(new Div(divisor)));
}
public static Precise operator / (Precise precise, int value)
{
return precise.Divide(value);
}
public Precise Add(int addend)
{
return new Precise(_value, _operation.Combine(new Plus(addend)));
}
public Precise Subtract(int minuend)
{
return Add(-minuend);
}
public static Precise operator + (Precise precise, int value)
{
return precise.Add(value);
}
public static Precise operator - (Precise precise, int value)
{
return precise.Subtract(value);
}
}
Here each Precise has both an integer value and an operation that will be performed on it. Further operations produce a new Precise (doing this sort of thing as a mutable is crazy) with a new operation but when possible those operations are combined into a single simpler operation. Hence "divide by three then multiply by six" becomes "multiply by two".
We can test this thus:
public static void Main(string[] args)
{
Precise A = 10;
A /= 3;
try
{
var test = (int)A;
}
catch(InvalidOperationException)
{
Console.Error.WriteLine("Invalid operation attempted");
}
A *= 6;
int result = (int)A;
Console.WriteLine(result);
// Let's do 10 / 5 * 2 = 4 because it works but can't be pre-combined:
Console.WriteLine(new Precise(10) / 5 * 2);
// Let's do 10 / 5 * 2 - 6 + 4 == 2 to mix in addition and subtraction:
Console.WriteLine(new Precise(10) / 5 * 2 - 6 + 4);
Console.Read();
}
A good solution would also deal well with operations done where the LHS was an integer and the RHS a Precise and where both where a Precise; left as an exercise for the reader ;)
Sadly we have to get much more complicated to handle (10 / 3 + 1) * 3, with the improvement having to be made in the Combine implementations.
Edit: Musing a bit further on the issues of doing the above well enough to catch at least most of the edge cases, I think it should start with only dealing with operations between two Precise objects, because going int -> Precise is trivial and can easily be put on top, but going Precise -> int requires a call to the calculation, perhaps too early. I'd also make the operations the key thing acted upon (have the operation store one or two objects which in turn contain an operation or a value). Then if you started with a representation of the sum (10 / 3) + 5 and multiplied it by 6 it's easier to turn that into (10 * (6 / 3)) + (5 * 6) which upon final calculation can give the precise result 50 rather than fail because it hits the imprecise 10 / 3.
If you don't allow arbitrary precision rationals, it seems that you are asking the impossible without more constraints.
Take 1 and divide it by 65537 twice, then multiply by 65537 twice to retrieve 1: this can't fit in 32 bits integers.
Then round final answer using Math.Round().
I would use a decimal for the result of operation and on the GetNumber check on the .ToString if there is a "." If yes I throw an Exception, if not I convert it to an int.

Help with mathematic operands in class (c#)

public class Racional<T>
{
private T nominator;
private T denominator;
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
I'm interested in this part :
public static Racional<int> operator *(Racional<int> a, Racional<int> b)
{
return ((int)(a.nominator + b.nominator, a.denominator + b.denominator));
}
What's wrong:
One of the parameters of a binary operator must be the containing type
How I can normaly code this part for mathematic operations?
The reason your code doesn't compile is explained by the compiler error. The containing type is a generic type definition, and a generic type constructed from such a type is not considered to be the same type.
I have a few questions:
Why must the Rational type be generic? A rational number is defined as a number that can be expressed as the quotient / fraction of two integers (where the denominator is not 0). Why not make the type non-generic and simply use int throughout? Or do you intend that the type be used for other integral types such as long and BigInteger? In that case, consider using something like Aliostad's suggestion if you want some code-sharing mechanism.
Why do you want the product of two rational numbers to be the equal to the sum of their numerators over the sum of their denominators? That doesn't make sense to me.
In any case, you appear to want to be able to 'generically' add two instances of an 'addable' type. Unfortunately, there currently isn't any way to express a 'has a suitable addition operator' constraint in C#.
Method #1: One workaround for this in C# 4 is to use the dynamic type to give you the desired "virtual operator" semantics.
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = (dynamic)a.Nominator + b.Nominator;
var denominatorSum = (dynamic)a.Denominator + b.Denominator;
return new Racional<T>(nominatorSum, denominatorSum);
}
The operator will throw if the type doesn't have a suitable addition operator.
Method #2: Another (more efficient) way is to use expression-trees.
First, create and cache a delegate that can perform the addition by compiling the appropriate expression:
private readonly static Func<T, T, T> Adder;
static Racional()
{
var firstOperand = Expression.Parameter(typeof(T), "x");
var secondOperand = Expression.Parameter(typeof(T), "y");
var body = Expression.Add(firstOperand, secondOperand);
Adder = Expression.Lambda<Func<T, T, T>>
(body, firstOperand, secondOperand).Compile();
}
(The static constructor will throw if the type doesn't have a suitable addition operator.)
Then employ it in the operator:
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
var nominatorSum = Adder(a.Nominator, b.Nominator);
var denominatorSum = Adder(a.Denominator, b.Denominator);
return new Racional<T>(nominatorSum, denominatorSum);
}
The issue here is you are defining an operator for Racional<int> in the class Racional<T>. This is not possible. The types are not the same, you can only define operator for Racional<T>.
Generics cannot express generalization of operators since they are defined only for a certain types. Solution is to create a class and inherit from Racional<int>:
public class IntRacional : Racional<int>
{
public static Racional<int> operator +(IntRacional a, IntRacional b)
{
return new Racional<int>()
{
Nominator = a.Nominator + b.Nominator,
Denominator = a.Denominator + b.Denominator
};
}
}
To solve your issue, you need to provide conversion functions from T to some type where operator+ is defined and vice versa. Assuming Int64 is big enough in most cases, this can be done this way:
public class Racional<T>
{
private T nominator;
private T denominator;
static Converter<T,Int64> T_to_Int64;
static Converter<Int64,T> Int64_to_T;
public static void InitConverters(Converter<T,Int64> t2int, Converter<Int64,T> int2t )
{
T_to_Int64 = t2int;
Int64_to_T = int2t;
}
public T Nominator
{
get { return nominator; }
set { nominator = value; }
}
public T Denominator
{
get { return denominator; }
set { denominator = value; }
}
public Racional(T nominator, T denominator)
{
this.nominator = nominator;
this.denominator = denominator;
}
public static Racional<T> operator *(Racional<T> a, Racional<T> b)
{
return new Racional<T>(
Int64_to_T(T_to_Int64(a.nominator) + T_to_Int64(b.nominator)),
Int64_to_T(T_to_Int64(a.denominator) + T_to_Int64(b.denominator)));
}
// By the way, should this not be * instead of + ???
//
// public static Racional<T> operator *(Racional<T> a, Racional<T> b)
// {
// return new Racional<T>(
// Int64_to_T(T_to_Int64(a.nominator) * T_to_Int64(b.nominator)),
// Int64_to_T(T_to_Int64(a.denominator) * T_to_Int64(b.denominator)));
// }
public override string ToString()
{
return "(" + this.nominator + " " + this.denominator + ")";
}
}
Of course, this has the drawback that you must provide the initialization of those converters somewhere at the program start, should look like this:
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
In a real program, you may know which possible replacements for T you are going to use. So one can provide those 3 or 4 calls in a static constructor like this:
public static Racional()
{
Racional<int>.InitConverters(x => (Int64)x, y => (int)y);
Racional<short>.InitConverters(x => (Int64)x, y => (short)y);
Racional<Int64>.InitConverters(x => (Int64)x, y => (Int64)y);
}
should be sufficient in most cases. Note that this converter initialization is repeated for all 3 types 3 times again, re-initializing the conversion functions multiple times again. In practice this should not make any trouble.

Method using Func<T,TResult> as parameters

I need some help on simplifying my method
I have this method
public double ComputeBasicAmount(double basicLimit, double eligibleAmt)
{
return basicLimit * eligibleAmt;
}
sample usage:
Foo foo = new Foo(100, 1000);
double basicAmt = ComputeBasicAmount(foo.BasicLimit, foo.EligibleAmt)
The problem here is I want the eligibleAmt to be dynamic because sometimes
it's not really only the eligbleAmt what I'm passing to the method.. like this
Foo foo = new Foo(100, 1000);
double basicAmt = ComputeBasicAmount(foo.BasicLimit, foo.EligibleAmt/foo.RoomRate)
My solution is use the Func delegate as a parameter but i don't know how to use it properly
i want something functional like this
public double ComputeBasicAmount<T>(double basicLimit, Func<T, double> multiplier)
{
return basicLimt * multiplier;
}
double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate)
can someone help me. thanks in advance...
If the multiplier depends on the item then either you'll need to pass the item as well, or you'll need to return a Func<T, double>:
public double ComputeBasicAmount<T>(double basicLimit,
Func<T, double> multiplier,
T item)
{
return basicLimt * multiplier(item);
}
...
double basicAmt = ComputeBasicAmount<Foo>(
foo.BasicLimit,
x => x.EligibleAmt / x.RoomRate,
foo)
or
public Func<T, double> ComputeBasicAmount<T>(double basicLimit,
Func<T, double> multiplier)
{
return item => basicLimt * multiplier(item);
}
...
var basicAmtFunc = ComputeBasicAmount<Foo>(
foo.BasicLimit,
x => x.EligibleAmt / x.RoomRate);
var basicAmt = basicAmntFunc(foo);
If neither of those is what you were looking for, please explain where you want the actual value of T to be provided so that you can work out the multiplier.
The first is very similar to just having a Func<double> to compute the multiplier, of course... which in turn is pretty much like calling that Func<double> when computing the arguments, to get back to your original version which just takes two doubles.
You can declare it simply as a Func<double> (that way you are not making the method dependent on the Foo type), and pass any method taking no parameters and returning a double as argument:
public static double ComputeBasicAmount(double basicLimit, Func<double> multiplier)
{
return basicLimit * multiplier();
}
Some example calls:
class Foo
{
public double One;
public double Two;
}
Foo f = new Foo();
double result = ComputeBasicAmount(f.One, () => f.Two);
You can also have some other method returning a double
public static double GetDoubleValue()
{
return 4.2;
}
...and pass that as argument:
double result = ComputeBasicAmount(42,GetDoubleValue);
You should use a Func<double> since you only use the double result
public double ComputeBasicAmount(double basicLimit, Func<double> multiplier)
{
return basicLimt * multiplier();
}
Then call it like this
double basicAmt = ComputeBasicAmount<Foo>(foo.BasicLimit, x => x.EligibleAmt/x.RoomRate)
But then you could have a regular double parameter instead.
You'd declare your method something like this, so the multiplier is a delegate that takes a Foo object and returns a double:
double ComputeBasicAmount(
double basicLimit, Foo foo, Func<Foo, double> multiplier)
Then call it like this, passing a lambda into the multiplier:
double basicAmt = ComputeBasicAmount(
foo.BasicLimit, foo, x => x.EligibleAmt / x.RoomRate);
Thanks guys, With your help I was able to make my existing code much more readable and functional...
class RNB
{
public RNB(double roomRate, double roomDays)
{
RoomRate = roomRate;
RoomDays = roomDays;
}
public double RoomRate { get; set; }
public double RoomDays { get; set; }
public const double BasicLimit = 100;
}
class HMS
{
public double Amount { get; set; }
public const double BasicLimit = 200;
}
public static double ComputeBasicAmount(double basicLimit, Func<double> multiplier)
{
return basicLimit * multiplier();
}
static void Main(string[] args)
{
RNB rnb = new RNB(100, 2);
double result = ComputeBasicAmount(RNB.BasicLimit, () => rnb.RoomDays * rnb.RoomRate);
Console.WriteLine("RNB Basic Amt: " + result.ToString());
HMS hms = new HMS() { Amount = 1000 };
result = ComputeBasicAmount(HMS.BasicLimit, () => hms.Amount);
Console.WriteLine("HMS Basic Amt: " + result.ToString());
Console.Read();
}
But I have another problem here.. I Want to eliminate the passing of the BasicLimit because i think it looks redundant here. Is it possible to put the BasicLimit inside the ComputeBasicAmount method
Something like this..
public static double ComputeBasicAmount<T>(Func<T, double> multiplier, T obj)
{
return obj.BasicLimit * multiplier();
}
But I have to put this question in another thread because I think its another topic...
See you guys there... thanks...

Categories