Can Nullable be used as a functor in C#? - c#

Consider the following code in C#.
public int Foo(int a)
{
// ...
}
// in some other method
int? x = 0;
x = Foo(x);
The last line will return a compilation error cannot convert from 'int?' to 'int' which is fair enough. However, for example in Haskell there is Maybe which is a counterpart to Nullable in C#. Since Maybe is a Functor I would be able to apply Foo to x using fmap. Does C# have a similar mechanism?

We can implement such functionality ourselves:
public static class FuncUtils {
public static Nullable<R> Fmap<T, R>(this Nullable<T> x, Func<T, R> f)
where T : struct
where R : struct {
if(x != null) {
return f(x.Value);
} else {
return null;
}
}
}
Then we can use it with:
int? x = 0;
x = x.Fmap(Foo);
It will thus call the function Foo if x is not null. It will wrap the result back in a Nullable<R>. In case x is null, it will return a Nullable<R> with null.
Or we can write a more equivalent function (like fmap in Haskell) where we have a function Fmap that takes as input a Func<T, R> and returns a Func<Nullable<T>, Nullable<R>> so that we can then use it for a certain x:
public static class FuncUtils {
public static Func<Nullable<T>, Nullable<R>> Fmap<T, R>(Func<T, R> f)
where T : struct
where R : struct {
return delegate (Nullable<T> x) {
if(x != null) {
return f(x.Value);
} else {
return null;
}
};
}
}
We can then use it like:
var fmapf = FuncUtils.Fmap<int, int>(Foo);
fmapf(null); // -> null
fmapf(12); // -> Foo(12) as int?

Functor
Not only can you turn Nullable<T> into a functor, but C# actually understands functors, enabling you to write something like this:
x = from x1 in x
select Foo(x1);
If you prefer method call syntax, that's also possible:
x = x.Select(Foo);
In both cases, you need an extension method like this:
public static TResult? Select<T, TResult>(
this T? source,
Func<T, TResult> selector) where T : struct where TResult : struct
{
if (!source.HasValue)
return null;
return new TResult?(selector(source.Value));
}
Monad
Not only does C# understand functors, but it understands monads as well. Add these SelectMany overloads as well:
public static TResult? SelectMany<T, TResult>(
this T? source,
Func<T, TResult?> selector)
where T : struct
where TResult : struct
{
if (!source.HasValue)
return null;
return selector(source.Value);
}
public static TResult? SelectMany<T, U, TResult>(
this T? source,
Func<T, U?> k,
Func<T, U, TResult> s)
where T : struct
where TResult : struct
where U : struct
{
return source
.SelectMany(x => k(x)
.SelectMany(y => new TResult?(s(x, y))));
}
This enables you to write queries like this:
var result = from x in (int?)6
from y in (int?)7
select x * y;
Here, result is an int? containing the number 42.

If you have an extension method:
public int Foo(this int a)
{
// ...
}
you can do:
// in some other method
int? x = 0;
x = x?.Foo();
The ?. operator will ensure Foo is called only if x is not null. If x is null, it is not called (a null of the return type is used instead).
Otherwise, the canonical way to write it is naturally:
x = x.HasValue ? Foo(x.Value) : (int?)null;
Of course you can create your own Maybe infrastructure if you will (Willem Van Onsem's answer).

Related

What are the ways I can write this differently? - static bool M (int x) => x%2 == 0;

I'm currently studying for a test and I've looked up what Function, Action and Predicate mean and I know that only Action doesn't have a return value and Predicate returns a bool value which is what I need in my question. This is the code I got in the question:
static bool M (int x) => x%2 == 0;
These are the potential answers given:
A) Func <bool, int> A = M;
B) Func <int, bool> B = M;
C) Action <int, bool> C = M;
D) Predicate <int> D = M;
Based on what I've learned and some simple logic it should be B and D, right? Can someone confirm this for me?
Let's ask the compiler:
Clearly A) & C) are compiler errors. So, B) & C) are correct.
The Func<int, bool> delegate for B) looks like this:
public delegate TResult Func<in T, out TResult>(T arg);
And the Predicate<int> delegate for D) looks like this:
public delegate bool Predicate<in T>(T obj);
Both match the signature for M.
You can call a static function by it's class. For example:
public class yourClass
{
> public static void DoSomething(bool isTrue)
> {
> //Here you can do some things
> }
}
yourClass.DoSomething(true);
if you want a function to return some value eg bool, string etc
Public class yourClass
{
>public static bool DoSomething(bool isTrue)
>{
>>if(isTrue)
>>{
>>return false;
>>}
>>else
>>{
>>return true;
>>}
>}
}
bool isItTrue = yourClass.DoSomething(true);
A function that returns a value must always have a return value. If you remove the else-part from the example above, you will get an error that not all code returns a value.

Get nested property for ordering from Expression<Func<T,Tkey>> [duplicate]

I'm creating a Validator<T> class. I'm attempting to implement the Linq SelectMany extension methods for my validator to be able to compose expressions using a Linq query and validate the final result even when the underlying values change.
The following test code demonstrates my intent.
var a = 2;
var b = 3;
var va = Validator.Create(() => a, n => n >= 0 && n < 5);
var vb = Validator.Create(() => b, n => n >= 0 && n < 5);
var vc = from ia in va
from ib in vb
select ia + ib;
Debug.Assert(vc.Value == a + b); //2 + 3
Debug.Assert(vc.Value == 5);
Debug.Assert(vc.IsValid == true);
a = 7;
Debug.Assert(vc.Value == a + b); //7 + 3
Debug.Assert(vc.Value == 10);
Debug.Assert(va.IsValid == false);
Debug.Assert(vb.IsValid == true);
Debug.Assert(vc.IsValid == false);
I've seen the following question How do I compose existing Linq Expressions which shows me how to compose two Func<T, bool>'s together using an And expression, but I need to be able to compose functions together in a more, well, functional way.
I have, for example, the following two expressions:
public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }
I wish to create a new expression like this:
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions rather than compile & invoke.
}
}
More succinctly I'm trying to create these functions:
// Specific case
Func<Expression<Func<T>>, Expression<Func<T, bool>>, Expression<Func<bool>>>
// General case
Func<Expression<Func<X, Y>>, Expression<Func<Y, Z>>, Expression<Func<X, Z>>>
The general case function can be modified to accept different numbers of generic arguments as needed to compose any function.
I've searched Stack Overflow (of course) and the web, but haven't an example that solves this issue.
My code for the Validator<T> class is below.
public class Validator<T>
{
public Validator(Expression<Func<T>> valueFunc,
Expression<Func<T, bool>> validationFunc)
{
this.ValueExpression = valueFunc;
this.ValidationExpression = validationFunc;
}
public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }
public T Value { get { return this.ValueExpression.Compile().Invoke(); } }
public bool IsValid { get { return this.IsValidExpression.Compile().Invoke(); } }
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions.
}
}
}
My SelectMany extensions contain loads of yucky .Compile().Invoke() which I want to get rid of.
public static Validator<U> SelectMany<T, U>(this Validator<T> #this, Expression<Func<T, Validator<U>>> k)
{
Expression<Func<T>> fvtv = #this.ValueExpression;
Expression<Func<Validator<U>>> fvu = () => k.Compile().Invoke(fvtv.Compile().Invoke());
Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
Expression<Func<U, bool>> fvtiv = u => #this.ValidationExpression.Compile().Invoke(fvtv.Compile().Invoke());
return fvuv.ToValidator(fvtiv);
}
public static Validator<V> SelectMany<T, U, V>(this Validator<T> #this, Expression<Func<T, Validator<U>>> k, Expression<Func<T, U, V>> s)
{
Expression<Func<Validator<U>>> fvu = () => #this.SelectMany(k);
Expression<Func<T>> fvtv = #this.ValueExpression;
Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
Expression<Func<T, bool>> fvtiv = #this.ValidationExpression;
Expression<Func<U, bool>> fvuiv = u => fvu.Compile().Invoke().ValidationExpression.Compile().Invoke(u);
Expression<Func<V>> fvv = () => s.Compile().Invoke(fvtv.Compile().Invoke(), fvuv.Compile().Invoke());
Expression<Func<V, bool>> fvviv = v => fvtiv.Compile().Invoke(fvtv.Compile().Invoke()) && fvuiv.Compile().Invoke(fvuv.Compile().Invoke());
return fvv.ToValidator(fvviv);
}
Thanks in advance!
While dtb's answer works for several scenarios, it is suboptimal as such an expression cannot be used in Entity Framework, as it cannot handle Invoke calls. Unfortunately, to avoid those calls one needs a lot more code, including a new ExpressionVisitor derived class:
static Expression<Func<A, C>> Compose<A, B, C>(Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var ex = ReplaceExpressions(f.Body, f.Parameters[0], g.Body);
return Expression.Lambda<Func<A, C>>(ex, g.Parameters[0]);
}
static TExpr ReplaceExpressions<TExpr>(TExpr expression,
Expression orig,
Expression replacement)
where TExpr : Expression
{
var replacer = new ExpressionReplacer(orig, replacement);
return replacer.VisitAndConvert(expression, nameof(ReplaceExpressions));
}
private class ExpressionReplacer : ExpressionVisitor
{
private readonly Expression From;
private readonly Expression To;
public ExpressionReplacer(Expression from, Expression to)
{
From = from;
To = to;
}
public override Expression Visit(Expression node)
{
return node == From ? To : base.Visit(node);
}
}
This replaces every instance of the first parameter in the first expression with the expression in the second expression. So a call like this:
Compose((Class1 c) => c.StringProperty, (Class2 c2) => c2.Class1Property
Would yield the expression (Class2 c2) => c2.Class1Property.StringProperty.
The equivalent of Haskell's function composition operator
(.) :: (b->c) -> (a->b) -> (a->c)
f . g = \ x -> f (g x)
would in C# probably be something like
static Expression<Func<A, C>> Compose<A, B, C>(
Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var x = Expression.Parameter(typeof(A));
return Expression.Lambda<Func<A, C>>(
Expression.Invoke(f, Expression.Invoke(g, x)), x);
}
Is this what you're looking for?
Example:
Compose<int, int, string>(y => y.ToString(), x => x + 1).Compile()(10); // "11"

C# generic operators - RTTI approach

I intend to ask about generic operator+ overloading but not in typical "can I do operator+ for generic type" way.
Questions are on the bottom
I recently started to create matrix class in C# and after a while It came to me that I cannot do simple T + T !
Thus, I googled and googled and found several workarounds.
Create Expression link
Create abstract class abstract class Matrix<T>{//some code}. Create 'protected virtual method Add(T itemToAdd)' and then create
operator like this : T operator+(T item1, T item2){return item1.Add(item2);}(most posts on stack) and then inherit this method in class Matrix : Matrix<int> here
Use method Add such as : T Add(T first, T second){ dynamic output = first + second; return output;} (somewhere on stack)
First one just does not suited me so I tried second one but then I run onto serious problems like:
(A LOT of )repetative code - I created 4 classes for : int, double, long, Complex - my own type
Creating multiple extension methods and so on.
Third one is just so unsafe that I rejected it immidietlay.
After my struggling I came to realise : 'Why don't I use RTTI and reflection?' I know, it is expensive in running time but why not use static constructor to do this?
Here is my idea (pseudocode):
class Matrix<T>{
static Func<T,T,T> Add;
static Matrix
{
if(T is int)
Add = (first,second) = > ((int)first)+((int)second);
else if(T is long)
Add = (first,second) = > ((long)first)+((long)second);
// and so on for built-in types
else
{ // T is not built-in type
if(typeof(T).GetMethods().Contains("op_Addition"))
{
Add = (first,second) => typeof(T).getMethod("op_Addition").invoke(first,second);
}
}
}
I know that reflection is costly but it will do it only one time (per type)!
And before you start argue : I am going to code T is int like this :
var type = typeof(T);
if(type==typeof(int)) // code
I am aware that I cannot explicitly convert T to int but there must be some sort of 'work around'. Problem is that (for example) Int32 has not explicit 'method' for operator+ hence, reflection is not of much use.
After all that introduction I have two questions :
Is it a good approach or do you see major flaws in it?
Is it doable? I don't want to start creating code without knowing for sure that my lambda function WILL work.
EDIT 1+2
I changed my code to generic.
I figured that maybe you need an usage of my class, here you are :
Matrix<int> matrix = new Matrix(1,1); // creates int-based matrix
Matrix<MyClass> matrix2 = new Matrix(1,1); // creates some other type matrix
ANSWER
based on dasblinkenlight's answer I managed to do this :
public interface ITypeTratis<T>
{
T Add(T a, T b);
T Mul(T a, T b);
T Sub(T a, T b);
T Div(T a, T b);
bool Eq(T a, T b);
}
public class IntTypeTratis : ITypeTratis<int>
{
//code for int
}
public class DoubleTypeTratis : ITypeTratis<double>
{
//code for double
}
internal class TypeTraits<T> : ITypeTratis<T>
{
public Func<T, T, T> AddF;
public Func<T, T, T> MulF;
public Func<T, T, T> DivF;
public Func<T, T, T> SubF;
public Func<T, T, bool> EqF;
public T Add(T a, T b) => AddF(a, b);
public bool Eq(T a, T b) => EqF(a, b);
public T Mul(T a, T b) => MulF(a, b);
public T Sub(T a, T b) => SubF(a, b);
public T Div(T a, T b) => DivF(a, b);
}
public class Matrix<T>
{
private static IDictionary<Type, object> traitByType = new Dictionary<Type, object>()
{
{typeof (int), new IntTypeTratis()},
{typeof (double), new DoubleTypeTratis()}
};
static Matrix()
{
Debug.WriteLine("Robie konstruktor dla " + typeof(T));
var type = typeof(T);
if (!traitByType.ContainsKey(type))
{
MethodInfo add, sub, mul, div, eq;
if ((add = type.GetMethod("op_Addition")) == null)
throw new NotSupportedException("Addition is not implemented");
if ((sub = type.GetMethod("op_Subtraction")) == null)
throw new NotSupportedException("Substraction is not implemented");
if ((mul = type.GetMethod("op_Multiply")) == null)
throw new NotSupportedException("Multiply is not implemented");
if ((div = type.GetMethod("op_Division")) == null)
throw new NotSupportedException("Division is not implemented");
if ((eq = type.GetMethod("op_Equality")) == null)
throw new NotSupportedException("Equality is not implemented");
var obj = new TypeTraits<T>
{
AddF = (a, b) => (T)add.Invoke(null, new object[] { a, b }),
SubF = (a, b) => (T)sub.Invoke(null, new object[] { a, b }),
MulF = (a, b) => (T)mul.Invoke(null, new object[] { a, b }),
DivF = (a, b) => (T)div.Invoke(null, new object[] { a, b }),
EqF = (a, b) => (bool)eq.Invoke(null, new object[] { a, b })
};
traitByType[type] = obj;
}
}
}
And this is exactly what I was looking for.
Yes, your approach will work fine.
Your static constructor will run for each type parameter T, ensuring that Add is set correctly.
You may want to separate out the addition logic into a separate class outside your matrix, and use that class to run operations based on type for your matrix. For example, if you also need multiplication, you could build a ITypeTraits<T> interface that has Add and Multiply:
public interface ITypeTraits<T> {
T Add(T a, T b);
T Mul(T a, T b);
}
Now you can build implementations of ITypeTraits<T> for individual types, e.g.
public class IntTypeTraits : ITypeTraits<int> {
public int Add(int a, int b) { return a+b; }
public int Mul(int a, int b) { return a*b; }
}
public class LongTypeTraits : ITypeTraits<long> {
public long Add(long a, long b) { return a+b; }
public long Mul(long a, long b) { return a*b; }
}
... // and so on
make a dictionary out of them
static readonly IDictionary<Type,object> traitByType = new Dictionary<Type,object> {
{typeof(int), new IntTypeTraits() }
, {typeof(long), new LongTypeTraits() }
... // and so on
};
and get the one you need to perform operations:
ITypeTraits<T> traits = (ITypeTraits<T>)traitByType(typeof(T));
T first = ...
T second = ...
T sum = traits.Add(first, second);
T prod = traits.Mul(first, second);
We can do this natively in C# 11 / .NET 7 (or above):
class Matrix<T> where T : INumber<T> // or just IAdditionOperators<T,T,T>
{
T x, y, z; // just to show we can do things
public T Sum() => x + y + z;
}
What is wrong with #3? You can just check for type, like so:
public abstract class Matrix<T>
{
public static HashSet<Type> AllowAdd = new HashSet<Type>
{
typeof(int),
typeof(long),
typeof(string),
typeof(double),
};
public T Add<T>(T first, T second)
{
if(!AllowAdd.Contains(typeof(T)))
{
throw new Exception(string.Format("Cannot preform addition for type: {0}", typeof(T).Name));
}
dynamic result = (dynamic)first + (dynamic)second;
return (T)result;
}
}
Bulding on dasblinkenlight's answer, here's my version of it. The benefit is that it doesn't need a dictionary lookup, instead making the type system do it. Should be faster, I think, but I haven't measured it. Also a bit less typing.
public abstract class MatrixBase
{
protected static class OperationDict<T>
{
private static Func<T,T,T> _notSupported = (a, b) => { throw new NotSupportedException(string.Format("Type {0} not supported for Matrix operations!", typeof(T))); };
public static Func<T, T, T> Add = _notSupported;
public static Func<T, T, T> Multiply = _notSupported;
}
static MatrixBase()
{
OperationDict<int>.Add = (a, b) => a + b;
OperationDict<int>.Multiply = (a, b) => a * b;
OperationDict<decimal>.Add = (a, b) => a + b;
OperationDict<decimal>.Multiply = (a, b) => a * b;
// Etc. for all supported types
}
}
public class Matrix<T> : MatrixBase
{
public T DoAdd(T a, T b)
{
return OperationDict<T>.Add(a, b);
}
}
I think you are on the right path, in order to avoid using reflection, you are required to somehow inform the compiler that you know "T" has the "+" operator, however, this feature does not yet exist in C#, so this is impossible to implement without runtime type checking or imposing other constraints.
If you don't care about the performance, you could use dynamic:
(dynamic)first + (dynamic)second
but that will take several reflection performance hits in every operation
Or you could use some other more complex approach that caches the specific methods in a dictionary, but you won't escape calling at least .GetType() in your add's implementation

Use a delegate for the equality comparer for LINQ's Distinct()

I have a LINQ Distinct() statement that uses my own custom comparer, like this:
class MyComparer<T> : IEqualityComparer<T> where T : MyType
{
public bool Equals(T x, T y)
{
return x.Id.Equals(y.Id);
}
public int GetHashCode(T obj)
{
return obj.Id.GetHashCode();
}
}
...
var distincts = bundle.GetAllThings.Distinct(new MyComparer<MySubType>());
This is all fine and dandy and works as I want. Out of curiosity, do I need to define my own Comparer, or can I replace it with a delegate? I thought I should be able to do something like this:
var distincts = bundle.GetAllThings.Distinct((a,b) => a.Id == b.Id);
But this doesn't compile. Is there a neat trick?
Distinct takes an IEqualityComparer as the second argument, so you will need an IEqualityComparer. It's not too hard to make a generic one that will take a delegate, though. Of course, this has probably already been implemented in some places, such as MoreLINQ suggested in one of the other answers.
You could implement it something like this:
public static class Compare
{
public static IEnumerable<T> DistinctBy<T, TIdentity>(this IEnumerable<T> source, Func<T, TIdentity> identitySelector)
{
return source.Distinct(Compare.By(identitySelector));
}
public static IEqualityComparer<TSource> By<TSource, TIdentity>(Func<TSource, TIdentity> identitySelector)
{
return new DelegateComparer<TSource, TIdentity>(identitySelector);
}
private class DelegateComparer<T, TIdentity> : IEqualityComparer<T>
{
private readonly Func<T, TIdentity> identitySelector;
public DelegateComparer(Func<T, TIdentity> identitySelector)
{
this.identitySelector = identitySelector;
}
public bool Equals(T x, T y)
{
return Equals(identitySelector(x), identitySelector(y));
}
public int GetHashCode(T obj)
{
return identitySelector(obj).GetHashCode();
}
}
}
Which gives you the syntax:
source.DistinctBy(a => a.Id);
Or, if you feel it's clearer this way:
source.Distinct(Compare.By(a => a.Id));
It's unfortunate that Distinct doesn't come up with such an overload, so what you have is a good option.
With MoreLinq, you can use the DistinctBy operator.
var distincts = bundle.GetAllThings.DistinctBy(a => a.Id);
You might also want to consider writing a generic ProjectionEqualityComparer that can turn the appropriate delegate into an IEqualityComparer<T> implementation, such as the one listed here.
Here is my perverse dirty little vanilla C# trick:
entities
.GroupBy(e => e.Id)
.Select(g => g.First())
This link shows how to create the extension method to be able to use Distinct in the manner you gave. You'll need to write two Distinct extension methods, and one IEqualityComparer.
Here's the code, from the site:
public static class Extensions
{
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer)
{
return source.Distinct(new DelegateComparer<T>(comparer));
}
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer, Func<T,int> hashMethod)
{
return source.Distinct(new DelegateComparer<T>(comparer,hashMethod));
}
}
public class DelegateComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> _equals;
private Func<T,int> _getHashCode;
public DelegateComparer(Func<T, T, bool> equals)
{
this._equals = equals;
}
public DelegateComparer(Func<T, T, bool> equals, Func<T,int> getHashCode)
{
this._equals = equals;
this._getHashCode = getHashCode;
}
public bool Equals(T a, T b)
{
return _equals(a, b);
}
public int GetHashCode(T a)
{
if (_getHashCode != null)
return _getHashCode(a);
else
return a.GetHashCode();
}
}
As of NET6, a DistinctBy extension method was added to the library in System.Linq.
example:
Planet[] planets =
{
Planet.Mercury,
Planet.Venus,
Planet.Earth,
Planet.Mars,
Planet.Jupiter,
Planet.Saturn,
Planet.Uranus,
Planet.Neptune,
Planet.Pluto
};
foreach (Planet planet in planets.DistinctBy(p => p.Type))
{
Console.WriteLine(planet);
}
// This code produces the following output:
// Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
// Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
// Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
// Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }

Passing an operator along with other parameters

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.");

Categories