Passing an operator along with other parameters - c#

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

Related

Overloading a method with delegates in c#

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

Create an array that points to only part of another array?

I have a huge array that contains reference type elements, and I want to create a lot of other arrays that essentially just point to specific parts of that one big array.
In other words, I want to create "indexers" or "pointers with lengths".
In C++ it's easy to do so using pointers and for each pointer assign a length, for example create a struct which contains a pointer with a length.
How can I achieve this in C#/.NET?
The whole point is to avoid copying anything, I just want pointers to specific parts in an array that already exists in memory.
Any ideas?
Jon's suggestion of using ArraySegment<T> is likely what you want. If however you are wanting to represent a pointer to the interior of an array, the way you can in C++, here's some code for that. No warranty is expressed or implied, use at your own risk.
This code does not track the "length" of the interior pointer in any way, but it is quite easy to add that feature if you want.
internal struct ArrayPtr<T>
{
public static ArrayPtr<T> Null { get { return default(ArrayPtr<T>); } }
private readonly T[] source;
private readonly int index;
private ArrayPtr(ArrayPtr<T> old, int delta)
{
this.source = old.source;
this.index = old.index + delta;
Debug.Assert(index >= 0);
Debug.Assert(index == 0 || this.source != null && index < this.source.Length);
}
public ArrayPtr(T[] source)
{
this.source = source;
index = 0;
}
public bool IsNull()
{
return this.source == null;
}
public static bool operator <(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index < b.index;
}
public static bool operator >(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index > b.index;
}
public static bool operator <=(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index <= b.index;
}
public static bool operator >=(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index >= b.index;
}
public static int operator -(ArrayPtr<T> a, ArrayPtr<T> b)
{
Debug.Assert(Object.ReferenceEquals(a.source, b.source));
return a.index - b.index;
}
public static ArrayPtr<T> operator +(ArrayPtr<T> a, int count)
{
return new ArrayPtr<T>(a, +count);
}
public static ArrayPtr<T> operator -(ArrayPtr<T> a, int count)
{
return new ArrayPtr<T>(a, -count);
}
public static ArrayPtr<T> operator ++(ArrayPtr<T> a)
{
return a + 1;
}
public static ArrayPtr<T> operator --(ArrayPtr<T> a)
{
return a - 1;
}
public static implicit operator ArrayPtr<T>(T[] x)
{
return new ArrayPtr<T>(x);
}
public static bool operator ==(ArrayPtr<T> x, ArrayPtr<T> y)
{
return x.source == y.source && x.index == y.index;
}
public static bool operator !=(ArrayPtr<T> x, ArrayPtr<T> y)
{
return !(x == y);
}
public override bool Equals(object x)
{
if (x == null) return this.source == null;
var ptr = x as ArrayPtr<T>?;
if (!ptr.HasValue) return false;
return this == ptr.Value;
}
public override int GetHashCode()
{
unchecked
{
int hash = this.source == null ? 0 : this.source.GetHashCode();
return hash + this.index;
}
}
public T this[int index]
{
get { return source[index + this.index]; }
set { source[index + this.index] = value; }
}
}
Now we can do stuff like:
double[] arr = new double[10];
var p0 = (ArrayPtr<double>)arr;
var p5 = p0 + 5;
p5[0] = 123.4; // sets arr[5] to 123.4
var p7 = p0 + 7;
int diff = p7 - p5; // 2
It sounds like you're looking for something like ArraySegment<T>. Contrary to my earlier thoughts, it does have an indexer and implement IEnumerable<T> etc - it's just done with explicit interfaces.
Sample code:
using System;
using System.Collections.Generic;
static class Test
{
static void Main()
{
string[] original = { "The", "quick", "brown", "fox", "jumped", "over",
"the", "lazy", "dog" };
IList<string> segment = new ArraySegment<string>(original, 3, 4);
Console.WriteLine(segment[2]); // over
foreach (var word in segment)
{
Console.WriteLine(word); // fox jumped over the
}
}
}
EDIT: As noted in comments, ArraySegment<T> is only really "fully functional" in .NET 4.5. The .NET 4 version doesn't implement any interfaces.
You could use LINQ:
yourArray.Skip(startIndex).Take(numberToTake)
The query is lazily evaluated.

How to compare values of two objects in C#

I created a struct
public struct MyCalender : IComparable<MyCalender>
{
public int CompareTo(PersianDate other)
{
return DateTime.Compare(this, other);
}
.
.
.
.
.
}
I new two object of this in a other UserControl, and i want compare they.
I use this code but i get error.
MyCalender value = new MyCalender(2010,11,12);
MyCalender value2 = new MyCalender(2010,11,12);
if (value < value2) ==> geterror
IComparable exposes CompareTo. < and > must be overloaded separately:
class Foo : IComparable<Foo>
{
private static readonly Foo Min = new Foo(Int32.MinValue);
private readonly int value;
public Foo(int value)
{
this.value = value;
}
public int CompareTo(Foo other)
{
return this.value.CompareTo((other ?? Min).value);
}
public static bool operator <(Foo a, Foo b)
{
return (a ?? Min).CompareTo(b) < 0;
}
public static bool operator >(Foo a, Foo b)
{
return (a ?? Min).CompareTo(b) > 0;
}
}
I edited the code so that it does not fail when comparing against null. To keep it brief I used a shortcut that works unless value is Int32.MinValue for a proper Foo. Strictly speaking you'd have to check for null explicitly to get the contract right:
By definition, any object compares greater than (or follows) null, and
two null references compare equal to each other.
Besides, implementing IComparable<T> means that CompareTo(T value) takes a parameter of T. Therefore MyCalendar : IComparable<MyCalender> should implement a method CompareTo(MyCalendar other) rather than PersianDate (or implement IComparable<PersianDate>).
You should either use CompareTo method that you already implemented instead of > in the line you posted or you need to overload > and < operators for your specific class. For instance:
public static bool operator >(MyCalendar c1, MyCalendar c2)
{
return c1.CompareTo(c2) > 0;
}
public static bool operator <(MyCalendar c1, MyCalendar c2)
{
return c1.CompareTo(c2) < 0;
}
But keep in mind that you have to overload both of them.
if comparing just a datetime object,
would something like
DateTime A = DateTime.Now, B = DateTime.Now.AddMinutes(1);
var isqual = A.Date.CompareTo(B.Date);
do the trick?
or something like:
class Calender
{
public DateTime datetime { get; set;}
}
class DateComparer : Calender, IComparable<Calender>
{
public int CompareTo(Calender other)
{
return other.datetime.Date.CompareTo(this.datetime.Date);
}
}

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.

Why is 1 && 2 in C# false?

I got frustated with my other question. So i wrote up this example.
In C the below is true. See demo
int main()
{
printf("%d", 1 && 2);
return 0;
}
Output:
1
In C#. It is FALSE. WHY is this false?
Also i dont understand why i needed to create the bool operator in this example but not the one in my other question but no matter. Why is the below false? it makes no sense to me.
BTW the logic making the below false is described here
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyInt a=1, b=2;
bool res=a && b;
Console.WriteLine("result is {0}", res);
}
class MyInt
{
public int val;
public static bool operator true(MyInt t) { return t.val != 0; }
public static bool operator false(MyInt t) { return t.val == 0; }
public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }
public static MyInt operator |(MyInt l, MyInt r) { return l.val | r.val; }
public static implicit operator MyInt(int v) { return new MyInt() { val = v }; }
public static implicit operator bool(MyInt t) { return t.val != 0; }
}
}
}
In C there is no bool. Convention is that 0 is false and != 0 is true. if statement treated conditional expression result exactly that way.
In C++ bool was introduced. But it was compatible with old rules, 0 treated as false and false as 0, and there was implicit conversion between int and bool.
In C# it is not the same way: there is bool and int and they are not convertible to eachother. That is what C# Standard says. Period.
So when you tried to reimplement bool and int compatibility you made a mistake. You use && which is logical operator, but in C# you can't override it and only &, which is implemented as bitwise. 1 & 2 == 0 == false! here it is!
You even should not overload bitwise ones, to maintain compatibility you just have to leave operator true and false.
This code works as you expect:
class Programx
{
static void Main(string[] args)
{
MyInt a = 1, b = 2;
bool res = a && b;
Console.WriteLine("result is {0}", res);
}
class MyInt
{
public int val;
public static bool operator true(MyInt t)
{
return t.val != 0;
}
public static bool operator false(MyInt t)
{
return t.val == 0;
}
public static implicit operator MyInt(int v)
{
return new MyInt() { val = v };
}
public static implicit operator bool(MyInt t)
{
return t.val != 0;
}
}
}
result is True
Your implementations of operator& and operator| are wrong. These binary operators have bitwise meanings when applied to integral types, and when applied to either Boolean types or classes that have their own & and | operators, they have logical AND and OR semantics (being the non-short-circuiting cousins of && and ||). Correct implementations would look as follows:
operator &(MyInt l, MyInt r) {return l.val != 0 && r.val != 0);}
operator |(MyInt l, MyInt r) {return l.val != 0 || r.val != 0);}
I'll try and make this simple, since I think people are overcomplicating this.
var x = 1 & 2;
// behind the scenes: 0001 AND 0010 = 0000
Console.Write(x); // 0, as shown above
Integers can NOT be used as booleans in C#. The result of:
if (1 && 2) // compile error
var x = 1 && 2; // compile error
There is no point to asking why an Integer can not be used as a boolean in C#, it just can't. The type system does not allow it. If one were to implement their own Integer class, they could provide implicit conversions from their type to bool, but int does not do this. You also have to make a choice when overloading; do you want bitwise behaviour, or logical behaviour. You can not have both.
Some languages allow 0, "", [] as 'falsey' values. C# does not. Get over it, and use a bool if you're doing boolean logic. If all else fails, Convert.ToBoolean on an int will return true for all non-zero values.
public static MyInt operator &(MyInt l, MyInt r) { return l.val & r.val; }
If I read the linked article correctly, res = a && b will be "expanded" to:
MyInt.false(a) ? a : MyInt.&(a, b)
MyInt.false(a) is false, so evaluates to:
MyInt.&(a, b)
which "expands" to:
a.val & b.val
which is (1 & 2) == 0, and thus false.

Categories