Is there some way I can "overload" a function using delegates? I'd like to have a system in place wherein I can pass an anonymous function in a constructor and save it in a member variable. Data type isn't really an issue, but the passed functions can have one or two parameters. I've tried using (params double[] vals) in the delegate definition, but that complicates the passed anonymous functions and allows more parameters than should be allowed.
So I've created two empty methods to hold the two types. As an example:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public evalDelegate eval; //method used for two value inputs. Assigned in constructor.
public calcDelegate calc; //method used for single value input. Assigned in constructor.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return eval(values[0], values[1]);
}
//more stuff
}
}
Ultimately, what I'd like to do is more like this:
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public ???????? calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
eval = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return calc(values[0]);
}
else
{
return calc(values[0], values[1]);
}
//more stuff
}
}
I'm not tremendously familiar with C#, yet, but surely there is a way to do something like this without having to define an instance of one delegate or the other that will just go unused.
I'll throw my hat into the ring...
Here is how you would use a Func.
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public object func;
//constructor initializes all variables.
public OpWrapper(int p, Func<double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a single parameter
operands = 1;
precedence = p;
rightAssoc = a;
func = f;
}
//overloaded constructor assigns the proper method.
public OpWrapper(int p, Func<double, double, double> f, bool a = false)
{
//No need to pass in o, we can infer from context that its a double parameter
operands = 2;
precedence = p;
rightAssoc = a;
func = f;
}
public double evaluate(params double[] values)
{
if (values.Length != operands)
throw new InvalidOperationException("Invalid number of operands");
//do stuff
if (operands == 1)
{
return ((Func<double, double>)func)(values[0]);
}
else
{
return ((Func<double, double, double>)func)(values[0], values[1]);
}
//more stuff
}
}
Note that I removed "o" from the call, and that I used casting to choose the right operation (and checked if the proper number of operands was provided).
.Net provides some useful delegate types out of the box; namely Action for a void returning method and Func for one retaining an argument. These provide type safety over anonymous delegates and provide a clean approach to what you need which appears to be something like the Command or the Strategy pattern.
You can also use expressions to declare delegates inline as follows:
public void InvokeAction(Action invoke)
{
invoke();
}
InvokeAction(() => Console.WriteLine(...));
=> essentially means 'into' and if you had arguments you would declare them before the arrow:
(arg1, arg2) => ...
Expressions and Action/Func have all but taken over from anonymous delegates in modern .Net coding.
If you have a property of type Action on a class you call it as a method directly.
public Action Calc { get; set; }
Calc = () => Console.WriteLine(...);
Calc();
this will help you. In this i have just initialise your calc variable as object which is base type of all types (int,class,delegates etc) and in evaluate method i have cast it from object to its appropriate type.
public class OpWrapper
{
public int operands; //the number of operands this operator needs.
public int precedence; //the precedence this operator gets when calculating.
public bool rightAssoc; //whether or not this operator is right associative (true) or left associative (false).
public delegate double evalDelegate(double a, double b);
public delegate double calcDelegate(double a);
public object calc; //method that does the passed function.
//constructor initializes all variables.
public OpWrapper(int o, int p, evalDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new evalDelegate(f);
}
//overloaded constructor assigns the proper method.
public OpWrapper(int o, int p, calcDelegate f, bool a = false)
{
operands = o;
precedence = p;
rightAssoc = a;
calc = new calcDelegate(f);
}
public double evaluate(params double[] values)
{
//do stuff
if (operands == 1)
{
return (calc as calcDelegate)(values[0]);
}
else
{
return (calc as evalDelegate)(values[0], values[1]);
}
//more stuff
}
}
Related
Updated: How could I make a method with two paramerters to take any primitive number type, like int, uint, float, double, etc, (except bool)?
I'm currently using an object, but that means the method can accept any type.
public int[] MyNumberMethod(object a, object b)
{
if (a is int || a is uint || a is short || a is ushort || a is long || a is ulong || a is byte || a is sbyte || a is float || a is double || a is decimal)
{
if (b is int || b is uint || b is short || b is ushort || b is long || b is ulong || b is byte || b is sbyte || b is float || b is double || b is decimal)
return new int[] { Convert.ToInt32(b), Convert.ToInt32(a) };
}
return new int[] { 0, 0 };
}
This might not be as good as the other answers, but another option is to create your own structure where you only allow a value of certain data types:
public struct Number
{
#region Static methods and fields
private static readonly Type[] allowedTypes = new Type[] {
typeof(int), typeof(uint), typeof(short), typeof(ushort),
typeof(long), typeof(ulong), typeof(byte), typeof(sbyte),
typeof(float), typeof(double), typeof(decimal)
};
private static void CheckIsNumber(dynamic val) {
if (Array.IndexOf(allowedTypes, val.GetType()) == -1) { throw new InvalidCastException("Input type must be a number."); }
}
#endregion
#region Constructor
public Number(dynamic Value) {
Number.CheckIsNumber(Value);
_value = Value;
}
#endregion
#region Properties
private dynamic _value;
public dynamic Value {
get { return _value; }
set {
Number.CheckIsNumber(value);
_value = value;
}
}
#endregion
#region Overridden methods
public override bool Equals(object obj) { return _value.Equals(obj); }
public override int GetHashCode() { return _value.GetHashCode(); }
public override string ToString() { return _value.ToString(); }
#endregion
#region Conversion operators - Number
public static implicit operator Number(uint val) { return new Number(val); }
public static implicit operator Number(short val) { return new Number(val); }
public static implicit operator Number(ushort val) { return new Number(val); }
public static implicit operator Number(long val) { return new Number(val); }
public static implicit operator Number(ulong val) { return new Number(val); }
public static implicit operator Number(byte val) { return new Number(val); }
public static implicit operator Number(float val) { return new Number(val); }
public static implicit operator Number(double val) { return new Number(val); }
public static implicit operator Number(decimal val) { return new Number(val); }
#endregion
#region Conversion operators - Misc. data types
public static implicit operator int(Number num) { return (int)num.Value; }
public static implicit operator uint(Number num) { return (uint)num.Value; }
public static implicit operator short(Number num) { return (short)num.Value; }
public static implicit operator ushort(Number num) { return (ushort)num.Value; }
public static implicit operator long(Number num) { return (long)num.Value; }
public static implicit operator ulong(Number num) { return (ulong)num.Value; }
public static implicit operator byte(Number num) { return (byte)num.Value; }
public static implicit operator sbyte(Number num) { return (sbyte)num.Value; }
public static implicit operator float(Number num) { return (float)num.Value; }
public static implicit operator double(Number num) { return (double)num.Value; }
public static implicit operator decimal(Number num) { return (decimal)num.Value; }
#endregion
}
Every time you change the value or create a new instance of the structure it will verify if the input value's data type matches any of the items in the allowedTypes array. If not it will throw an InvalidCastException.
I have also added conversion operators which will let you use this as a normal number, thus you can use it pretty much like you would use any other numerical data type:
Number myNum = 3.5;
myNum += 10.4;
double something = myNum - 6.0;
However keep in mind that you must add a decimal point when working with double, float, etc. or else it will assume that the number is an integer:
Number myNum = 3.5;
myNum -= 2;
MessageBox.Show(myNum.ToString()); //Shows "1" as the second line converts 'myNum' into an integer.
All that said, here's how you would use it for your method:
public int[] MyNumberMethod(Number a, Number b)
{
try {
return new int[] { Convert.ToInt32(b), Convert.ToInt32(a) };
}
catch(InvalidCastException) {
return new int[] { 0, 0 };
}
}
And thanks to the conversion operators you won't need to specify a (Number) conversion. For example:
byte myByte = 133;
//Unnecessary.
MyNumberMethod((Number)17.4, (Number)myByte);
//This works just as fine.
MyNumberMethod(17.4, myByte);
Well since you want to use all primitive types except the bool, how about that?
public int MyNumberMethod<T>(T number) where T : struct
{
if (!(number is bool) && number.GetType().IsPrimitive)
return Convert.ToInt32(number);
return 0;
}
e.g.
MyNumberMethod<short>(5);
All numeric types (except double and float) are implicitly convertible to decimal and float is implicitly convertible to double. So if you make overloads like:
Method(double, double)
Method(decimal, double)
Method(decimal,decimal)
Method(double, decimal)
Your method will be callable with any two numbers but only with any two numbers.
First you must call other function like GenericNumberMethod, that will contain the calling to MyNumberMethod. You must have for each data type an implementacion of GenericNumberMethod with the corresponding parameter
public int MyNumberMethod(object number) {
return Convert.ToInt32(number);
}
public int GenericNumberMethod(int number) {
return MyNumberMethod(number);
}
public int GenericNumberMethod(decimal number) {
return MyNumberMethod(number);
}
I have a client application that uses classes (and enums) from an external dll which is loaded at runtime and reflected. I know what methods I am expecting to find in the dll and what I am expecting its enums to be called.
I would like to create a delegate that I can use in the client application and which is created from the reflected method at runtime. This approach works when the delegate just has "standard" types, but how can I get this to work if the dll method takes an enum? I can't declare the enum in the delegate as an object since it's a value type, trying the Enum or int does not seem to work either. Is there a way around this? Any help gratefully received!
// e.g. external code
namespace test2
{
public static class test2
{
public static int calc(int a, int b, testEnum c)
{
if (c == testEnum.add) return a + b;
else return a - b;
}
public static int add(int a, int b)
{
return a + b;
}
}
public enum testEnum
{
add, subtract
}
}
// my client code
namespace test1
{
public class TestClient
{
private static Assembly _assembly;
public static void SetUp()
{
const string externalDll = ".../test2.dll";
Assembly assembly = Assembly.LoadFrom(externalDll);
AppDomain.CurrentDomain.Load(assembly.GetName());
_assembly = assembly;
}
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, ??? c); // nothing works here
private _calc calc;
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // not OK
// intended usage
var reflectedEnum = ReflectMe("testEnum", "add");
int threeAgain = calc(1, 2, reflectedEnum);
}
public static T GetExpectedFunction<T>(string functionName) where T : class
{
try
{
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = _assembly.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
catch (Exception e)
{
// "Error binding to target method!"
}
}
}
}
You can bind a delegate with object type to a method taking an enum by creating, at runtime, a dynamic method call with LINQ Expression, and adding data conversions for parameters whose types don't match:
public static T GetExpectedFunction<T>(string functionName) where T : class {
try {
if (!typeof(T).IsSubclassOf(typeof(Delegate))) throw new ApplicationException("GetExpectedFunction must return a delegate!");
var foundMethod = Type.GetType("test2.test2").GetMethod(functionName, BindingFlags.Public | BindingFlags.Static);
var inv = typeof(T).GetMethod("Invoke");
var parameters = inv.GetParameters().Zip(foundMethod.GetParameters(), (a, b) => new {
PassedIn = a.ParameterType
, Reflected = b.ParameterType
, Parameter = Expression.Parameter(a.ParameterType)
}).ToList();
if (parameters.All(p => p.PassedIn == p.Reflected)) {
// Bind directly
return (T)(object)Delegate.CreateDelegate(typeof(T), foundMethod);
}
var call = Expression.Call(foundMethod, parameters.Select(
p => p.PassedIn==p.Reflected
? (Expression)p.Parameter
: Expression.Convert(p.Parameter, p.Reflected)
));
return (T) (object) Expression.Lambda(typeof(T), call, parameters.Select(p => p.Parameter)).Compile();
} catch (Exception e) {
// "Error binding to target method!"
return null;
}
}
This implementation pairs up types from the reflected and the delegate methods (see parameters variable), and creates ParameterExpression objects for types that come from the delegate. Then it checks if all parameter types match up (the parameters.All(...) part). This is an optimization for situations when conversions are unnecessary.
If at least one conversion is necessary, the code creates a method call that substitutes the original parameter expressions with conversion expressions where types do not match up, creates a lambda of the requested delegate type, compiles it, and returns it to the caller.
For your code this dynamic method would look like this:
int dynamic_method(int a, int b, object c) {
return test2.test2(a, b, (testEnum)c);
}
There is one solution, you have to create faked Enum (it will be better if you create the exact enum), then you will pass as integer like this:
private delegate int _add(int a, int b);
private _add add;
private delegate int _calc(int a, int b, FakedEnum c); // faked enum here
private _calc calc;
public enum FakedEnum
{
}
public void Run()
{
SetUp();
add = GetExpectedFunction<_add>("add");
int three = add(1, 2); // OK
calc = GetExpectedFunction<_calc>("calc"); // it will be ok
var result= calc(4, 6, (FakedEnum)0);
// intended usage
// var reflectedEnum = ReflectMe("testEnum", "add");
//int threeAgain = calc(1, 2, reflectedEnum);
}
Use dynamic keyword to declare your delegate parameter:
private delegate int _calc(int a, int b, dynamic c);
I have a problem with operator resolution on generic methods.
From my understanding of section 7.3.4 of the spec within the function EqualOperatorGeneric (sample code below) the correct overload of the == operator on the type A should be found, but instead it seems to get the candidate for (object, object).
Am I doing something very obvious wrong? Is there a method to get the expected behaviour and if not can I turn the given case into a compile time or runtime error?
public class A
{
public A(int num)
{
this.Value = num;
}
public int Value { get; private set; }
public override bool Equals(object obj)
{
var other = obj as A;
if (Object.ReferenceEquals(other, null))
return false;
return Object.Equals(this.Value, other.Value);
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public static bool operator ==(A l, A r)
{
if (Object.ReferenceEquals(l, null))
{
return !Object.ReferenceEquals(r, null);
}
return l.Equals(r);
}
public static bool operator !=(A l, A r)
{
return !(l == r);
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine(EqualOperatorGeneric(new A(1), new A(1)));
}
public static bool EqualOperatorGeneric<L, R>(L l, R r)
where L : class
where R : class
{
return l == r;
}
}
Output:
False
When EqualOperatorGeneric is compiled the == operator needs to be bound statically, when the method is compiled, to a single implementation. It is not bound separately for each separate usage of the generic method.
This is what differentiates generics from, say, C++ templates. The generic method is compiled once and then applied to every usage with every set of type arguments, whereas templates are compiled separately for each set of generic arguments.
After scrounging the spec I realized you can use the dynamic keyword to defer binding of the operator from compile time to runtime. This fixes the issues I have been having:
public static bool EqualOperatorGeneric<L, R>(L l, R r)
{
dynamic dl = l, dr = r;
return dl == dr;
}
Can I overload operators for class A in class B in C#? For example:
class A
{
}
class B
{
public static A operator+(A x, A y)
{
...
}
}
No; one of the parameters must be the containing type.
From section §10.10.2 of the language specification (version 4.0):
The following rules apply to binary operator declarations, where T denotes the instance type of the class or struct that contains the operator declaration:
• A binary non-shift operator must take two parameters, at least one of which must have type T or T?, and can return any type.
You should think about why. Here's one reason.
class A { }
class B { public static A operator+(A first, A second) { // ... } }
class C { public static A operator+(A first, A second) { // ... } }
A first;
A second;
A result = first + second; // which + ???
Here's another:
class A { public static int operator+(int first, int second) { // ... } }
Assume this allowed for a moment.
int first = 17;
int second = 42;
int result = first + second;
Per the specification for operator overload resolution (§7.3.2), A.+ will have precedence over Int32.+. We've just redefined addition for ints! Nasty.
No, you can't. error CS0563: One of the parameters of a binary operator must be the containing type
"In each case, one parameter must be the same type as the class or struct that declares the operator" quote from
Documentation on overloading operators.
Generally saying NO, but you can do something like following, if it helps :)
class A
{
public static A operator +(A x, A y)
{
A a = new A();
Console.WriteLine("A+"); // say A
return a;
}
}
class B
{
public static A operator +(A x, B y)
{
A a = new A();
Console.WriteLine("return in:A,B in out:A in class B+"); // say B
return a;
}
public static A operator +(B x, B y)
{
A a = new A();
Console.WriteLine("return in:B,B in out:A in class B +");
return a;
}
// and so on....
}
B b = new B();
A a = new A();
A a1 = new A();
B b1 = new B();
a = b + b1; // here you call operator of B, but return A
a = a + a1; // here you call operator of A and return A
To understand your problem, can i ask why you want to do that? :)
I have some VERY inefficient code in which many lines appear 4 times as I go through permutations with "<" and ">" operations and a variety of variables and constants. It would seem that there is a way to write the function once and pass in the operators along with the necessarily changing values and"ref" variables. What technique do I have to learn? "Delegates" have been suggested but I don't see how to use them in this manner. This is in C# 2.0, VS2005, but if the technique is generic and can be used with C++ too, that would be great.
Request for some code: The following appears in many guises, with different "<" and ">" signs as well as a mix of "+" and "-" signs:
if (move[check].Ypos - move[check].height / 200.0D < LayoutManager.VISIO_HEIGHT - lcac_c.top)
{
move[check].Ypos = move[check].Ypos + adjust;
.
.
.
In C++, use the std::less and std::greater functors. Both of these methods inherit std::binary_function, so your generic function should accept instances of this type.
In .NET, the equivalent to std::binary_function is Func<T, U, R>. There are no equivalents to std::less and std::greater, but it is fairly trivial to create them. See the following example.
static class Functor
{
static Func<T, T, bool> Greater<T>()
where T : IComparable<T>
{
return delegate(T lhs, T rhs) { return lhs.CompareTo(rhs) > 0; };
}
static Func<T, T, bool> Less<T>()
where T : IComparable<T>
{
return delegate(T lhs, T rhs) { return lhs.CompareTo(rhs) < 0; };
}
}
Note, the above code uses the Func<> class from .NET 3.5. If this is not acceptable, consider defining you own delegate.
C++ invocation example:
void DoWork(const std::binary_function<int, int, bool>& myOperator,
int arg1, int arg2)
{
if (myOperator(arg1, arg2)) { /* perform rest of work */ }
}
void main()
{
DoWork(std::less<int>(), 100, 200);
DoWork(std::greater<int>(), 100, 200);
}
C# invocation example:
void DoWork(Func<int, int, bool> myOperator, int arg1, int arg2)
{
if (myOperator(arg1, arg2)) { /* perform rest of work */ }
}
void main()
{
DoWork(Functor.Less<int>(), 100, 200);
DoWork(Functor.Greater<int>(), 100, 200);
}
EDIT: I corrected the example of the functor class as applying < or > operators to a generic type doesn't work (in the same manner as it does with C++ templates).
In C# use delegates for passing the "<" and ">" operation to the code that's doing the work.
C# Example:
public delegate bool BooleanOperatorDelegate(int a, int b)
class OperatorsImplementer {
public bool OperatorLess(int a, int b) {
return a < b;
}
}
class AnotherOperatorsImplementer {
public bool OperatorLess(int a, int b) {
return (a + 1) < (b - 1);
}
}
class OperatorUser {
int DoSomethingObscene(int a, int b, BooleanOperatorDelegate operator) {
if (operator(a, b)) {
return 5;
}
else {
return -5;
}
}
}
You should also check that the delegate you get as a paramater is not NULL.
This is the C method for doing so:
bool (*operator_func)(float a, float b)
After defining the Enum Operator in the Comparer class
public static class Comparer
{
public static bool IsTrue<T, U>(T value1, Operator comparisonOperator, U value2)
where T : U
where U : IComparable
{
switch (comparisonOperator)
{
case Operator.GreaterThan:
return value1.CompareTo(value2) > 0;
case Operator.GreaterThanOrEqual:
return value1.CompareTo(value2) >= 0;
case Operator.LessThan:
return value1.CompareTo(value2) < 0;
case Operator.LessThanOrEqual:
return value1.CompareTo(value2) <= 0;
case Operator.Equal:
return value1.CompareTo(value2) == 0;
default:
return false;
}
}
public enum Operator
{
GreaterThan = 1,
GreaterThanOrEqual = 2,
LessThan = 3,
LessThanOrEqual = 4,
Equal = 5
}
}
You can make a call like this:
if (IsTrue(var1, Operator.GreaterThanOrEqual, var2))
Console.WriteLine("var1 is greater than var2");
else
Console
.WriteLine("Unfortunately var1 is not greater than or equal var2. Sorry about that.");