C# use an operation as a parameter - c#

I'm trying to make a function where I can give it an operation > < == != etc.
I was wondering if it is possible to set one of these as a parameter to a function,
ie: UseOperator("test", >, 0)
If not what would be the best way to handle something like this? Maybe an enum?

The most natural approach would be to pass a delegate, IMO, e.g. of type Func<int, int, bool>. Unfortunately you can't convert an operator directly to a delegate - but you could write methods pretty simply and use method group conversions:
public void UseOperator(string name, Func<int, int, bool> op, int value)
{
...
}
public static bool GreaterThan(int x, int y, value)
{
return x > y;
}
UseOperator("test", GreaterThan, 0);
Marc Gravell's work on generic operators in MiscUtil may be useful to you.

This is not possible but you could use function delegates:
UseOperator("test", (x, y) => x > y, 0);

How about parsing the operator as a string value?
UseOperator("Test", ">", 0)
private void UseOperator(string str1, string operator, int intVlue)
{
switch(operator)
{
case ">":
//.....
}
}

Related

c# generic method for mathematical operations

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;
}

C# Func<> and extension methods question

I have seen someone write below kind of Func<> pattern. And I am trying to experiment with Funcs and Lambdas to get the concepts right.
so ExperimentalSelect returns a Func (with 2 args and bool return value).
But I fail to understand that how all of the 3 return statements are valid (1 at a time).
public static Func<BinaryTreeNode<int>, int, bool> nodeSelector = (x, y) =>
{
return x.Value > y;
};
public static Func<int, int, bool> intSelector = (x, y) =>
{
return x > y;
};
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect (int number)
{
return nodeSelector; // seems straightforward, i agree this should work
// how does this work ? intSelector is different type Func<>
// and it is executing it here, thereby returning the bool type result
// and not Func<> type as the return type of this method should
return (x, y) => intSelector(number, number);
// and how does this work ? what is node here ?
// and SomeMethod returns bool and not Func<> type
return (node, x) => SomeMethod(node, number, true);
}
private static bool SomeMethod(BinaryTreeNode<int> node, int someNumber,
bool doSomething)
{
return node.Value < someNumber;
}
EDIT:
If an ext. method expects a func
IEnumerable<int> selected = tree.TakeWhile(ExperimentalSelect);
How does SomeMethod work here ?, it is not a Func<> !
What does this syntax mean: (node, x) => SomeMethod(node, number, true);
Where is the node or x in picture here ?
Your comments above the returns are not correct.
intSelector and SomeMethod are not executed there. They will only be executed, when the return value of ExperimentalSelect is executed.
return (x, y) => intSelector(number, number);
This defines an anonymous method with two parameters. One of type BinaryTreeNode<int> and one of type int and a return value of bool, because that's what's the return type of ExperimentalSelect. The body of this anonymous method is the call to intSelector which is executed only, when the anonymous method itself is executed. This means, the body of this anonymous method can be anything you wish. It can even be multiple statements:
return (x, y) => {
var temp;
temp = y;
y = x;
x = temp;
return intSelector(number, y);
}
The anonymous method then is returned and not the result of executing it.
Your return statement is equivalent to the following:
Func<BinaryTreeNode<int>, int, bool> result =
(x, y) => intSelector(number, number);
return result;
You can verify this yourself with your debugger. Add a break point inside intSelector and step over the return statement. You will see, the breakpoint will not be hit.
One important point is the following:
Func can be seen as a pointer to a function.
Func<BinaryTreeNode<int>, int, bool> result =
(x, y) => SomeMethod(x, number, true);
This will create an anonymous method and result will point to that anonymous method.
However, have a look at the following code:
Func<BinaryTreeNode<int>, int, bool, bool> result = SomeMethod;
In this case, result will directly point to SomeMethod. No anonymous method is created here. Note the difference in the type of result. Because the first code only executes SomeMethod in the body of the anonymous method, the type of result doesn't need to match the signature of SomeMethod. But in the second code, you directly assign SomeMethod to result and thus the type of result must match the signature of SomeMethod.
More:
Look at the following code:
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect (int number)
{
return (x, y) => intSelector(number, number);
}
Func<BinaryTreeNode<int>, int, bool> result = ExperimentalSelect(10);
Console.WriteLine(result(30, 20)); // writes false
It will print false, although 30 is bigger than 20. Why?
The reason is, that your anonymous method has x and y as input parameters, but they are not used anywhere in its body. Instead, you pass number as both parameters to intSelector. The value of number is 10, and 10 isn't greater than 10.
The correct way to write this code would be like this:
public static Func<BinaryTreeNode<int>, int, bool> ExperimentalSelect ()
{
return (x, y) => intSelector(x, y);
}
Func<BinaryTreeNode<int>, int, bool> result = ExperimentalSelect();
Console.WriteLine(result(30, 20)); // writes true
As you can see, I now pass x and y to intSelector. I also removed the parameter number from ExperimentalSelect, because it is not used anywhere.
Ask yourself - are these two lines of code also correct:
Func<BinaryTreeNode<int>, int, bool> a =
(x, y) => intSelector(number, number);
Func<BinaryTreeNode<int>, int, bool> b =
(node, x) => SomeMethod(node, number, true);
The answer - yes. As it is for the return statements in your code.
I think perhaps you're either slightly misunderstanding the syntax or perhaps not understanding exactly what a Func is (apologies if either is not the case).
You seem to think that in this case
return (x, y) => intSelector(number, number);
what gets returned is the intSelector(number, number) part. But in reality the whole thing after return keyword is a return value. You can rewrite it like this:
return (BinaryTreeNode<int> x, int y) => intSelector(number,number);
which is roughly equivalent to returning an anonymous delegate with two parameters of type BinaryTreeNode<int> and int which returns the value of type bool. So it's your Func<BinaryTreeNode<int>, int, bool> right there.
Basically, the part to the left of => describes arguments and the part to the right is the method body, and the return type of the whole thing is the return type of the body.
Take a look at Lambda Expressions article by Eric White, it'll make sense to you.

programmatically specify operator

Is it possible to specify an operator R where R can be an arithmetic, relational or logical operator ?
For example a function that calculates
c = a R b
where I can specify whether R is +, -, *, /
Can this be done in C# ?
A binary operator is any function which accepts two operands. It is simple to abstract this functionality using delegates, which are basically wrappers around methods (functions).
To make this clearer, we can define a generic method which does nothing more that invoke the delegate using specified parameters, and return its result:
public Tout GetResult<TIn, TOut>(TIn a, TIn b, Func<TIn, TIn, TOut> #operator)
{
return #operator(a, b);
}
And you could use it to pass any combination of parameters and operators:
private bool AreEqual(int a, int b)
{
return a.Equals(b);
}
private int Subtract(int a, int b)
{
return a - b;
}
You can then use the same generic method to do whatever operation you want:
// use the "AreEqual" operator
bool equal = GetResult(10, 10, AreEqual);
// use the "Subtract" operator
int difference = GetResult(10, 10, Subtract);
Using lambda expressions, you can even create the operator "on the fly", by specifying it as an anonymous method:
// define a "Product" operator as an anonymous method
int product = GetResult(10, 10, (a,b) => a*b);
You can do something very close to that using lambda:
Func<int, int, int> op = (x, y) => x + y; // or any other operator
And then use it like any other delegate:
int result = op(1, 2);
If the type in question were user-defined with overloaded operators, you could use reflection, but I'm afraid it's not possible for types like int.
Check out Expression Trees - http://msdn.microsoft.com/en-us/library/bb397951.aspx
It is possible to have operator overloading in C#, check some MSDN
http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

In overloading why the return type of the function is not considered? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Function overloading by return type?
Hi,
In overloading we say that the parameter list has to be different either by number or by type, but doesn't matter on the return type, Why is that so???
The function
//Function 1
int Add(int a, int b)
{return a+b;}
//Function 2
Double Add(Double a, Double b)
{return a+b;}
//Function 3
Double Add(int a, int b)
{return (Double)a+b;}
The functions 1 2 are overloaded, where as functions 1 and 3 are not ??? Reasons ???
Any help is really appreciated.
The compiler needs to know at compile time which function you are trying to call. If they differ only by return type, this is usually not possible. Consider, for example:
var result = Add(1, 2);
or
Console.WriteLine(Add(1, 2));
the compiler would not be able to know whether you want to execute function 1 or 3. And even if you did
double x = Add(1, 2);
the compiler would not know if you (a) want to call function 3 or (b) call function 1 and do an implicit widening conversion from int to double.
There are to many cases where that kind of overloading would not work. Here is two of them:
You don't care about the result of the method, and call it like this:
Add(3, 4);
Should this call method 1 or 3?
You use varto assign the result
var result = Add(3, 4);
This kind of overloading would be ambiguous at best, so therefore it's not allowed.
The other answers deal with why, but an aside: in C# you can simulate return-type based overloading by using (abusing?) implicit conversion operators (and deferring the operation):
using System;
class Program {
static void Main() {
int i = Add(3, 5); // prints: int overload called
double d = Add(3, 5); // prints: double overload called
}
static SuperMagicAdder Add(int a, int b)
{ return new SuperMagicAdder(a, b); }
}
struct SuperMagicAdder {
private readonly int a,b;
public SuperMagicAdder(int a, int b) { this.a = a; this.b = b; }
public override string ToString() { return a + "+" + b; }
public static implicit operator int (SuperMagicAdder value) {
Console.WriteLine("int overload called");
return value.a + value.b;
}
public static implicit operator double (SuperMagicAdder value) {
Console.WriteLine("double overload called");
return (double)value.a + value.b;
}
}
Note that interestingly, Anonymous Function Literals in C# are overloaded on their result type and it doesn't seem to pose any problems.
In C#, a lambda can be two very different things:
a piece of executable code (a subclass of Delegate actually)
an abstract representation of an operation (basically, an abstract syntax tree)
This is distinguished purely by the result type of the lambda literal:
Func<int, int> l = (i) => i + i * i;
is a piece of executable code. I can say
Console.WriteLine(l(3));
and I will get 12.
Expression<Func<int, int>> e = (i) => i + i * i;
is an abstract representation of that operation. I can say
Console.WriteLine(e);
and I will get
i => (i + (i * i))
Note that this is not just the original text. It really is an rendering of the abstract representation. The extra parentheses around the expression and inside it are there, because ToString() did an actual tree traversal of the AST and rendered it. The AST looks roughly like this:
And this
var v = (i) => i + i * i;
is simply illegal, because lambdas are overloaded on their result type, but the var keyword says "use the result type to figure out the type of v".
Allowing return types to be part of the signature would create major ambiguities in overload resolution.
For example, consider:
Add(2,3);
We are "throwing away" the value returned by the method, but which overload should be invoked?
It doesn't work well with implicit-typing, or with assigning the value to a variable that is compatible with either return-type. E.g.:
var sum = Add(2,3);
object sum = Add(2,3);

Is there a way to cast a function

I think it would greatly simplify function overloading if I could just write the case that takes the most parameters and then simply stuff each case having less parameters with dummy params. For example..
// Add two integers
Func<int, int, int> addInts = (x, y) => { return x + y; };
// Add one to an integer
Func<int, int> addOne = (x) => { return x++; };
// In this case Func takes 2 args and has 1 return
public int IntCalc(Func<int,int,int> operation, int param1, int param2)
{
return operation(param1, param2);
}
// In this case Func takes 1 arg and has 1 return
public int IntCalc(Func<int, int> operation, int param1, int param2)
{
// This cast would allow me to do the overload
Func<int, int, int> castedOperation = (Func<int, int, int>)addOne;
return IntCalc(castedOperation, param1, 0);
}
So is there a way to do this? Is this a horrible practice?
You can only cast if the parameter signatures are compatible. In your case you'd need to define a lamda since converting a function with one parameter to a function with two parameters makes no sense in general.
Func<int, int, int> castedOperation = (i1,i2)=>addOne(i1);
If it's good practice depends on the contract of how the delegate will be used. If your functions with less parameters can fulfill that contract then this lamda based conversion is perfectly fine.
As a sidenode your addOne function is really ugly. While the increment of x has no effect because the parameter gets copied and thus only the copy is incremented and discared, implementing it as return x+1; would be much nicer than return x++; since you don't actually want to modify x.
Apart from the accepted answer you should also change the addOne to operation. So complete function would be
// In this case Func takes 1 arg and has 1 return
public int IntCalc(Func<int, int> operation, int param1, int param2)
{
// This cast would allow me to do the overload
Func<int, int, int> castedOperation = (i1,i2)=>operation(i1);
return IntCalc(castedOperation, param1, 0);
}
If your all parameters are the same type you can use params
adder(bool sample, params int[] a)
{
....
}
adder(2,3,4);
also you can use Named Parameter in C# 4.0.
Your approach is useful in constructors (you can do this with them).

Categories

Resources