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.
Related
I am having a problem with C# giving the "Use of unassigned local variable" compile error. What am I missing?
// returns generic result of a function with error message
// why the function failed
public class Result
{
public bool isSuccess = true;
public string errorMessage = string.Empty;
public static implicit operator bool(Result r)
{
return r.isSuccess;
}
public static Result operator &(Result a, Result b)
{
return !a.isSuccess ? a : b;
}
public static Result operator |(Result a, Result b)
{
if (a.isSuccess)
{
return a;
}
if (b.isSuccess)
{
return b;
}
return new Result
{
isSuccess = false,
errorMessage = $"{a.errorMessage}\nOut{b.errorMessage}"
};
}
public static bool operator false(Result a)
{
return !a.isSuccess;
}
public static bool operator true(Result a)
{
return a.isSuccess;
}
}
static Result Func1(int nIn, out int nOut)
{
nOut = nIn + 1;
return new Result();
}
private static void Main(string[] args)
{
var resultA =
Func1(0, out var a1) &&
Func1(a1, out var a2); // compiles fine
var resultB =
Func1(0, out var b1) &&
Func1(b1, out var b2) &&
Func1(b2, out var b3); // Use of unassigned local variable 'b2'
}
I think this may be a bug in the compiler - I'd personally expect b2 to be definitely assigned there. The spec for definite assignment is pretty hairy though, so I'm not going to try to prove it one way or another right now. It's possible that the rules aren't "clever" enough to work out that the only way that (x && y) is true is if both x and y are evaluated, and so in (x && y) && z, z should be able to rely on both x and y having been evaluated.
However, it's fairly easy to work around, just with an extra pair of parentheses:
var resultB =
Func1(0, out var b1) &&
(Func1(b1, out var b2) && Func1(b2, out var b3));
This question already has answers here:
Why must we define both == and != in C#?
(13 answers)
Closed 7 years ago.
Unable To Overload != , Error 3 The operator
'ConsoleApplication13.pl.operator !=(ConsoleApplication13.pl,
ConsoleApplication13.pl)' requires a matching operator '==' to also be
defined C:\Users\htg\documents\visual studio
2013\Projects\ConsoleApplication13\ConsoleApplication13\Program.cs 37
28 ConsoleApplication13 .
class Program
{
static void Main(string[] args)
{
pl a ,b,c;
a= new pl();
b=new pl();
a.mark=99;
b.mark=10;
c = a+b;
if (c != b)
Console.WriteLine("is not equal");
else
Console.WriteLine("both are equal");
Console.WriteLine(c.mark);
Console.ReadLine();
}
}
class pl
{
public int mark;
public static pl operator+ ( pl a , pl b) // 1. here It Work's Perfectly At + overloading
{
pl mm = new pl();
mm.mark = a.mark + b.mark;
return mm;
}
public static bool operator!= (pl m , pl n) // 2. unable to overload
{
if (m.mark != n.mark)
return true;
else
return false;
}
}
Yes - C# requires that if you overload the != operator, you also overload the == operator. From the C# 5 specification, section 10.10.2:
Certain binary operators require pair-wise declaration. For every declaration of either operator of a pair, there must be a matching declaration of the other operator of the pair. Two operator declarations match when they have the same return type and the same type for each parameter. The following operators require pair-wise declaration:
operator == and operator !=
operator > and operator <
operator >= and operator <=
In this case, it looks like you want:
public static bool operator ==(pl m, pl n)
{
if (ReferenceEquals(m, n))
{
return true;
}
if (ReferenceEquals(m, null) || ReferenceEquals(n, null))
{
return false;
}
return m.mark == n.mark;
}
public static bool operator !=(pl m, pl n)
{
return !(m == n);
}
Note how != is implemented in terms of == - this is almost always the simplest approach to implementing these operators. Implement == fully as it's easier to think in terms of positives, and then implement != as the inverse. The ReferenceEquals checks are performed to mean that null == null is true, but anything non-null is not equal to null. (This is also a common optimization to ensure that x == x is true without performing any further tests.)
As noted in comments, it's also very unusual to overload == and != without also overriding GetHashCode and Equals(object); I'd also recommend implementing IEquatable<T>. You should implement those to be compatible with your == operator - the GetHashCode method would probably be best just returning mark.
When implementing != you have to implement == as well; it's highly recommended to override both Equals and GetHashCode:
class pl {
public int mark;
...
public override bool Equals(object obj) {
pl other = obj as pl;
return Object.ReferenceEquals(null, other) ? false : mark == other.mark;
}
public override int GetHashCode() {
return mark;
}
public static Boolean operator ==(pl left, pl right) {
// what if left or right or both are null?
if (Object.ReferenceEquals(left, right))
return true;
else if (Object.ReferenceEquals(left, null))
return false;
else if (Object.ReferenceEquals(null, right))
return false;
return left.mark == right.mark;
}
public static Boolean operator !=(pl left, pl right) {
return ! (left == right);
}
}
I am making a wrapper for a "word" in an emulator project. Its meant to put all my cast conversions all in one spot. I was just about to start implement all the overrides for math functions (+,-,/,8, shift, etc.) When it occured to me that shouldn't all the implicit's take care of that? Do I need to over ride >= and <= when I got > < and ==?
I thought I would ask this as while there are plenty of questions relating to how to create them, there aren't many on how much is enough. Here is the code below:
public struct word_t
{
ulong val;
word_t(ulong val) { this.val = val; }
public static implicit operator word_t(int a) { return new word_t((ulong)a); }
public static implicit operator word_t(long a) { return new word_t((ulong)a); }
public static implicit operator word_t(uint a) { return new word_t((ulong)a); }
public static implicit operator word_t(ulong a) { return new word_t((ulong)a); }
public static implicit operator int(word_t a) { return (int)a.val; }
public static implicit operator long(word_t a) { return (long)a.val; }
public static implicit operator uint(word_t a) { return (uint)a.val; }
public static implicit operator ulong(word_t a) { return (ulong)a.val; }
public static bool operator ==(word_t a, word_t b) { return a.val == b.val; }
public static bool operator !=(word_t a, word_t b) { return a.val != b.val; }
public static bool operator >(word_t a, word_t b) { return a.val > b.val; }
public static bool operator <(word_t a, word_t b) { return a.val < b.val; }
public override bool Equals(object obj) {
return obj.Equals(val);
}
public override int GetHashCode() {
return val.GetHashCode();
}
public override string toString() {
return val.ToString();
}
}
My gut tells me to "Trust the compiler" but my head always worries on how efficient it is.
PS I just realized I should override shifts because of the bit shifting of negative number problems, but for right now just imagine shifts just magically work like adds between uint and int.
I recommend this MSDN article: http://msdn.microsoft.com/en-us/library/8edha89s(v=VS.100).aspx
It shows the operators you can overload and any catches. You can overload <= and >= but they must be overloaded in pairs, as is true with == and != as well.
The complex match operators +=, etc are available if +, etc. is overloaded, etc.
>= and <=, however, are separate. That is, overloading > and == does not give you a >= operator implicitly.
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.");
I need to detect if a flag is set within an enum value, which type is marked with the Flag attribute.
Usually it is made like that:
(value & flag) == flag
But since I need to do this by generic (sometimes at runtime I event have only an "Enum" reference. I can not find an easy way to use the & operator. At the moment I make it like this:
public static bool IsSet<T>(this T value, T flags) where T : Enum
{
Type numberType = Enum.GetUnderlyingType(typeof(T));
if (numberType.Equals(typeof(int)))
{
return BoxUnbox<int>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(sbyte)))
{
return BoxUnbox<sbyte>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(byte)))
{
return BoxUnbox<byte>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(short)))
{
return BoxUnbox<short>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(ushort)))
{
return BoxUnbox<ushort>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(uint)))
{
return BoxUnbox<uint>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(long)))
{
return BoxUnbox<long>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(ulong)))
{
return BoxUnbox<ulong>(value, flags, (a, b) => (a & b) == b);
}
else if (numberType.Equals(typeof(char)))
{
return BoxUnbox<char>(value, flags, (a, b) => (a & b) == b);
}
else
{
throw new ArgumentException("Unknown enum underlying type " + numberType.Name + ".");
}
}
private static bool BoxUnbox<T>(object value, object flags, Func<T, T, bool> op)
{
return op((T)value, (T)flags);
}
But I don't like the never ending if - else blocks, so is there a way to cast these values that I can use the & operator or any other solution to check this?
For me it looks overcomplicated. How about this (keeping in mind that enum is always mapped to an integer value type):
public static bool IsSet<T>(T value, T flags) where T : struct
{
// You can add enum type checking to be perfectly sure that T is enum, this have some cost however
// if (!typeof(T).IsEnum)
// throw new ArgumentException();
long longFlags = Convert.ToInt64(flags);
return (Convert.ToInt64(value) & longFlags) == longFlags;
}
I wrote a set of extension methods for enums, in case you need it :
public static class EnumExtensions
{
private static void CheckEnumWithFlags<T>()
{
if (!typeof(T).IsEnum)
throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
if (!Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
}
public static bool IsFlagSet<T>(this T value, T flag) where T : struct
{
CheckEnumWithFlags<T>();
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flag);
return (lValue & lFlag) != 0;
}
public static IEnumerable<T> GetFlags<T>(this T value) where T : struct
{
CheckEnumWithFlags<T>();
foreach (T flag in Enum.GetValues(typeof(T)).Cast<T>())
{
if (value.IsFlagSet(flag))
yield return flag;
}
}
public static T SetFlags<T>(this T value, T flags, bool on) where T : struct
{
CheckEnumWithFlags<T>();
long lValue = Convert.ToInt64(value);
long lFlag = Convert.ToInt64(flags);
if (on)
{
lValue |= lFlag;
}
else
{
lValue &= (~lFlag);
}
return (T)Enum.ToObject(typeof(T), lValue);
}
public static T SetFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, true);
}
public static T ClearFlags<T>(this T value, T flags) where T : struct
{
return value.SetFlags(flags, false);
}
public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct
{
CheckEnumWithFlags<T>();
long lValue = 0;
foreach (T flag in flags)
{
long lFlag = Convert.ToInt64(flag);
lValue |= lFlag;
}
return (T)Enum.ToObject(typeof(T), lValue);
}
}
The main drawback is that you can't specify where T : Enum : it is explicitly forbidden ("Constraint cannot be special class 'System.Enum'"), so the extension methods will appear in intellisense for all structs... I added the CheckEnumWithFlags method to check that the type is actually an enum, and has the Flags attribute.
UPDATE : Jon Skeet recently started an interesting library called UnconstrainedMelody which does exactly the same sort of things, and works around the generic type constraint limitation mentioned above
This should do the job for enum types with any underlying types:
public static bool IsSet<T>(this T value, T flags) where T : struct
{
return (Convert.ToInt64(value) & Convert.ToInt64(flags)) ==
Convert.ToInt64(flags);
}
Convert.ToInt64 is used because a 64-bit integer is the "widest" integral type possible, to which all enum values can be cast (even ulong). Note that char is not a valid underlying type. It seems that it is not valid in C#, but it is in general valid in CIL/for the CLR.
Also, you can't enforce a generic type constraint for enums (i.e. where T : struct); the best you can do is use where T : struct to enforce T to be a value type, and then optionally perform a dynamic check to ensure that T is an enum type.
For completeness, here is my very brief test harness:
static class Program
{
static void Main(string[] args)
{
Debug.Assert(Foo.abc.IsSet(Foo.abc));
Debug.Assert(Bar.def.IsSet(Bar.def));
Debug.Assert(Baz.ghi.IsSet(Baz.ghi));
}
enum Foo : int
{
abc = 1,
def = 10,
ghi = 100
}
enum Bar : sbyte
{
abc = 1,
def = 10,
ghi = 100
}
enum Baz : ulong
{
abc = 1,
def = 10,
ghi = 100
}
}
Personally, I think that look fine because you've wrapped it into a single purpose function. If you had that code scattered through an entire program I think you would have some problems, but what you've created improves clarity everywhere it is used and the function itself is clear enough what it does.
Just my opinion of course.
You could though, use the is keyword, which might help a little
public static bool IsSet<T>(this T value, T flags) where T : Enum
{
if (value is int)
{
return ((int)(object)a & (int)(object)b) == (int)(object)b);
}
//etc...
Simply use the Enum.HasFlag() Method !
I have used this to compare flags
public static bool IsSet<T>(this T input, T match)
{
return (Convert.ToUInt32(input) & Convert.ToUInt32(match)) != 0;
}
Here you can do the different conversions. From int to short to long.
or...
public static bool IsSet(this Enum value, Enum compare)
{
int baseValue = value.ToInt32();
int compareValue = compare.ToInt32();
if (baseValue == 0)
return false;
return ((baseValue & compareValue) == compareValue);
}