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);
}
Related
I want to implement my own CustomNumber class, and have it comparable to all other primitive number datatypes (int, long, double, float, etc.) using the relational operators.
Is there a way to do that for all of them at once, or do I really have to override the ==, !=, >, <, >= and <= operators aswell as the Equals(T other) method for each single integral datatype?
I think I know how operator overloading works in general, but it feels like there must be some kind of shortcut in order to make my CustomNumber comparable to all primitive number datatypes using relational operators, instead of having to overload each of those 6 operators for each single datatype, which might quickly add up to about 100 overload definitions.
There is no shortcut per se, you have to implement all the operators and functionality for all the types you want to support, it can't read your mind.
Check out the decimal implementation.
For your sanity you will notice not everything needs to be overridden, this is done by the implementation of implicit operators:
public static implicit operator Decimal(byte value)
{
return new Decimal(value);
}
[CLSCompliant(false)]
public static implicit operator Decimal(sbyte value)
{
return new Decimal(value);
}
public static implicit operator Decimal(short value)
{
return new Decimal(value);
}
[CLSCompliant(false)]
public static implicit operator Decimal(ushort value)
{
return new Decimal(value);
}
public static implicit operator Decimal(char value)
{
return new Decimal(value);
}
public static implicit operator Decimal(int value)
{
return new Decimal(value);
}
[CLSCompliant(false)]
public static implicit operator Decimal(uint value)
{
return new Decimal(value);
}
public static implicit operator Decimal(long value)
{
return new Decimal(value);
}
[CLSCompliant(false)]
public static implicit operator Decimal(ulong value)
{
return new Decimal(value);
}
public static explicit operator Decimal(float value)
{
return new Decimal(value);
}
public static explicit operator Decimal(double value)
{
return new Decimal(value);
}
public static explicit operator byte(Decimal value)
{
return ToByte(value);
}
[CLSCompliant(false)]
public static explicit operator sbyte(Decimal value)
{
return ToSByte(value);
}
public static explicit operator char(Decimal value)
{
UInt16 temp;
try
{
temp = ToUInt16(value);
}
catch (OverflowException e)
{
throw new OverflowException(Environment.GetResourceString("Overflow_Char"), e);
}
return (char)temp;
}
public static explicit operator short(Decimal value)
{
return ToInt16(value);
}
[CLSCompliant(false)]
public static explicit operator ushort(Decimal value)
{
return ToUInt16(value);
}
public static explicit operator int(Decimal value)
{
return ToInt32(value);
}
[CLSCompliant(false)]
public static explicit operator uint(Decimal value)
{
return ToUInt32(value);
}
public static explicit operator long(Decimal value)
{
return ToInt64(value);
}
[CLSCompliant(false)]
public static explicit operator ulong(Decimal value)
{
return ToUInt64(value);
}
public static explicit operator float(Decimal value)
{
return ToSingle(value);
}
public static explicit operator double(Decimal value)
{
return ToDouble(value);
}
public static Decimal operator +(Decimal d)
{
return d;
}
public static Decimal operator -(Decimal d)
{
return Negate(d);
}
public static Decimal operator ++(Decimal d)
{
return Add(d, One);
}
public static Decimal operator --(Decimal d)
{
return Subtract(d, One);
}
[System.Security.SecuritySafeCritical] // auto-generated
public static Decimal operator +(Decimal d1, Decimal d2)
{
FCallAddSub(ref d1, ref d2, DECIMAL_ADD);
return d1;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static Decimal operator -(Decimal d1, Decimal d2)
{
FCallAddSub(ref d1, ref d2, DECIMAL_NEG);
return d1;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static Decimal operator *(Decimal d1, Decimal d2)
{
FCallMultiply(ref d1, ref d2);
return d1;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static Decimal operator /(Decimal d1, Decimal d2)
{
FCallDivide(ref d1, ref d2);
return d1;
}
public static Decimal operator %(Decimal d1, Decimal d2)
{
return Remainder(d1, d2);
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator ==(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) == 0;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator !=(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) != 0;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator <(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) < 0;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator <=(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) <= 0;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator >(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) > 0;
}
[System.Security.SecuritySafeCritical] // auto-generated
public static bool operator >=(Decimal d1, Decimal d2)
{
return FCallCompare(ref d1, ref d2) >= 0;
}
As partial shortcut you can limit your overrides to double which cover all regular "numeric" types at cost of compiler inserted cast. Always comparing to double is dangerous for larger integer values (int and smaller types will be precise always).
class MyType
{
public override bool Equals(object obj)
{
return base.Equals(obj);
}
public override int GetHashCode()
{
return base.GetHashCode();
}
public static bool operator == (MyType x, double c)
{
// write some real code here - this one does not have a value to compare to.
return c > 42;
}
// you need all several overrides for each operator to behave in expected way
// so calling the same one (a == b)
// from a != b, b != a, b == a is a way to keep them consistent
public static bool operator == (double c, MyType x)
{
return (x == c);
}
public static bool operator != (double c, MyType x)
{
return !(c == x);
}
public static bool operator != (MyType x, double c)
{
return !(x == c);
}
}
Notes
C#/ .NET do not have built in concept of "numeric" type - this is something people ask often enough (i.e. Is there a constraint that restricts my generic method to numeric types?, Generics - where T is a number?).
don't forget to implement IEquatable<T>, IComparable, IComparable<T>...
consider if it is actually useful for your "numbers" to be able to freely mix with other types - especially for comparison with imprecise float/double which already painful enough.
I need to return a method in an operator function.
public int Add()
{
return 1;
}
public static int operator +()
{
return Add;
}
I will need to do this for a multiply, subtract and divide operator/function too.
Thanks
You can't declare parameterless operators. You can declare an operator to return an appropriate delegate - e.g. Func<int> - but it would be a pretty odd thing to do, IMO.
If you can tell us more about what you're trying to achieve, we can probably help you to work out a cleaner design.
Here's a pretty strange example overloading the unary + operator:
using System;
class Weird
{
private readonly int amount;
public Weird(int amount)
{
this.amount = amount;
}
private int Add(int original)
{
return original + amount;
}
// Very strange. Please don't do this.
public static Func<int, int> operator +(Weird weird)
{
return weird.Add;
}
}
class Test
{
static void Main(string[] args)
{
Weird weird = new Weird(2);
Func<int, int> func = +weird;
Console.WriteLine(func(3));
}
}
EDIT: If you're just trying to implement a Rational type, you're more likely to want:
public struct Rational
{
// Other members
public Rational Add(Rational other)
{
...
}
public static Rational operator +(Rational left, Rational right)
{
return left.Add(right);
}
}
This is what you SEEM to be trying to do, but your example makes it difficult to tell. So, from your comments in other answers it looks like you want to add, subtract, multiply, divide Rational numbers, which means the result should be a Rational as well (not an int).
Thus, you could define each of your methods, then implement operators to call those. The operators are always static, thus you'd need to check for null and handle as appropriate (in this case, I'll just throw ArgumentNullException):
public class Rational
{
public Rational Add(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual addition result here
}
public static Rational operator +(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Add(right);
}
public Rational Subtract(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual subtraction result here
}
public static Rational operator -(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Subtract(right);
}
public Rational Multiply(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual multiplication result here
}
public static Rational operator *(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Multiply(right);
}
public Rational Divide(Rational other)
{
if (other == null) throw new ArgumentNullException("other");
return // <-- return actual division result here
}
public static Rational operator /(Rational left, Rational right)
{
if (left == null) throw new ArgumentNullException("left");
return left.Divide(right);
}
}
Simple. Just call the Add method:
return Add();
C Sharp - Lesson 18: Overloading Operators
I don't think you can overload the + operator for int's! You would have to create your own wrapper class or struct instead:
public struct MyInt
{
private int _value;
public MyInt(int value)
{
_value = value;
}
public int Value
{
get { return _value; }
}
public static MyInt operator +(MyInt a, MyInt b)
{
return new MyInt(a._value + b._value);
}
public static implicit operator MyInt(int intValue)
{
return new MyInt(intValue);
}
public static explicit operator int(MyInt x)
{
return x.Value;
}
}
Then you are free to do with '+' what ever you want to do with it.
The implicit operator automatically converts int's to MyInt. So you could assign like this: MyInt x = 7;
The explicit operator converts MyInt's to int's like: int i = (int)x; where x is a MyInt.
Code:
void Main()
{
C.F();
}
public class C
{
public static void F()
{
var a = new A { i = 1, d = 2.5m };
var b = new B(a);
I(b);
D(b);
}
static void I(int i) { Console.WriteLine("int is: " + i); }
static void D(decimal d) { Console.WriteLine("decimal is: " + d); }
}
public class A
{
public int i;
public decimal d;
}
public class B
{
A _a;
public B(A a) { _a = a; }
public static implicit operator int(B b) { return b._a.i; }
public static implicit operator decimal(B b) { return b._a.d; }
}
OUTPUT:
int is: 1
decimal is: 2.5
Comment out:
//public static implicit operator decimal(B b) { return b._a.d; }
OUTPUT:
int is: 1
decimal is: 1
What is going on when the second version runs and outputs 1 for both cases?
My guess is that the compiler sees that there is an implicit conversion from B to int, and an implicit (built-in) conversion from int to decimal, so that it can use both in sequence. In other words, the call becomes D((decimal)(int)b).
Note that nothing is being truncated; rather, an int is being promoted to a decimal. If instead you comment out the int conversion, I expect that I(b) will fail, since even though there is an implicit cast from B to decimal, there is no implicit cast from decimal to int.
when you comment that line out it takes the int operator because there is an implicit conversion of int to decimal...
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.
First of all the Boolean type is said to have a default marshal type of a four-byte value. So the following code works:
struct A
{
public bool bValue1;
public int iValue2;
}
struct B
{
public int iValue1;
public bool bValue2;
}
public static void Main()
{
int[] rawvalues = new int[] { 2, 4 };
A a = (A)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(A));
Assert.IsTrue(a.bValue1 == true);
Assert.IsTrue(a.iValue2 == 4);
B b = (B)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(B));
Assert.IsTrue(b.iValue1 == 2);
Assert.IsTrue(b.bValue2 == true);
}
Clearly these structures marshal independently just fine. The values are translated as expected. However, when we combine these structures into a "union" by declaring LayoutKind.Explicit like this:
[StructLayout(LayoutKind.Explicit)]
struct Broken
{
[FieldOffset(0)]
public A a;
[FieldOffset(0)]
public B b;
}
We suddenly find ourselves unable to correctly marshal these types. Here is the test code for the above structure and how it fails:
int[] rawvalues = new int[] { 2, 4 };
Broken broken = (Broken)Marshal.PtrToStructure(GCHandle.Alloc(rawvalues, GCHandleType.Pinned).AddrOfPinnedObject(), typeof(Broken));
Assert.IsTrue(broken.a.bValue1 != false);// pass, not false
Assert.IsTrue(broken.a.bValue1 == true);// pass, must be true?
Assert.IsTrue(true.Equals(broken.a.bValue1));// FAILS, WOW, WTF?
Assert.IsTrue(broken.a.iValue2 == 4);// FAILS, a.iValue1 == 1, What happened to 4?
Assert.IsTrue(broken.b.iValue1 == 2);// pass
Assert.IsTrue(broken.b.bValue2 == true);// pass
It's very humorous to see this express as true: (a.bValue1 != false && a.bValue1 == true && !true.Equals(a.bValue1))
Of course the bigger problem here is that a.iValue2 != 4, rather the 4 has been changed to 1 (presumably by the overlapped bool).
So the question: Is this a bug, or just failed as designed?
Background: this came from What is the difference between structures containing bool vs uint when using PInvoke?
Update: This is even stranger when you use large integer values (> 255) as only the byte that is used for the boolean is being modified to a 1, thus changing 0x0f00 to 0x0f01 for the b.bValue2. For a.bValue1 above it's not translated at all and 0x0f00 provides a false value for a.bValue1.
Update #2:
The most obvious and reasonable solution to the above issue(s) is to use a uint for the marshalling and expose boolean properties instead. Really solving the issue with a 'workaround' is not at question. I'm mostly wondering is this a bug or is this the behavior you would expect?
struct A
{
private uint _bValue1;
public bool bValue1 { get { return _bValue1 != 0; } }
public int iValue2;
}
struct B
{
public int iValue1;
private uint _bValue2;
public bool bValue2 { get { return _bValue2 != 0; } }
}
It is working as designed.
Here is what is happening:
Take the new int[] { 2, 4 } and lets marshal it into A, B, Broken, and Broken2.
The last is the same as Broken, but with fields' order reversed (first b, then a).
If we marshal the ints into these structures we get the following values in memory:
A: 1, 4
B: 2, 1
Broken: 2, 1
Broken2: 1, 4
So what is happening is the following:
When the marshaller encounters a boolean, the value of it is: bool = (original != 0);
When there are two fields that map into the same memory, the rules of the last field win
So for A, the first int gets converted to 1, for B, the second int gets converted to 1,
for Broken, since B is the last field, its rules apply, and hence the second int gets converted to 1. Similarly for Broken2.
The line commented with 'FAILS, WOW, WTF?' fails because of the way boolean comparison is performed. It is comparing 2 to 1:
IL_007e: ldc.i4.1
IL_007f: ldloca.s 3
IL_0081: ldflda valuetype Test/A Test/Broken::a
IL_0086: ldfld bool Test/A::bValue1
IL_008b: ceq
ceq ends up comparing 1 to the byte in bValue, which is 2.
The funny thing is that if (broken.a.bValue1) will test 'true' because it's non-zero.
As far as the other problem (broken.a.iValue2 == 4), it went away when I applied:
[MarshalAs (UnmanagedType.Bool)]
to both boolean fields in the structures. This makes sure the booleans are marshaled as an integer (4 bytes in .NET).
It would appear earlNameless is correct, as adding another structure of ints:
struct C
{
public int iValue1;
public int iValue2;
}
to the end of the union seems to correct at least part of the problem. However, this is still flawed since the boolean will only consider a single-byte value and as demonstrated is not dependable. Finally the best answer I've come up with is to use a custom type for the marshaling.
[Serializable]
[ComVisible(true)]
public struct BOOL : IComparable, IConvertible, IComparable<BOOL>, IEquatable<BOOL>, IComparable<bool>, IEquatable<bool>
{
private uint _data;
public BOOL(bool value) { _data = value ? 1u : 0u; }
public BOOL(int value) { _data = unchecked((uint)value); }
public BOOL(uint value) { _data = value; }
private bool Value { get { return _data != 0; } }
private IConvertible Convertible { get { return _data != 0; } }
#region IComparable Members
public int CompareTo(object obj) { return Value.CompareTo(obj); }
#endregion
#region IConvertible Members
public TypeCode GetTypeCode() { return Value.GetTypeCode(); }
public string ToString(IFormatProvider provider) { return Value.ToString(provider); }
bool IConvertible.ToBoolean(IFormatProvider provider) { return Convertible.ToBoolean(provider); }
byte IConvertible.ToByte(IFormatProvider provider) { return Convertible.ToByte(provider); }
char IConvertible.ToChar(IFormatProvider provider) { return Convertible.ToChar(provider); }
DateTime IConvertible.ToDateTime(IFormatProvider provider) { return Convertible.ToDateTime(provider); }
decimal IConvertible.ToDecimal(IFormatProvider provider) { return Convertible.ToDecimal(provider); }
double IConvertible.ToDouble(IFormatProvider provider) { return Convertible.ToDouble(provider); }
short IConvertible.ToInt16(IFormatProvider provider) { return Convertible.ToInt16(provider); }
int IConvertible.ToInt32(IFormatProvider provider) { return Convertible.ToInt32(provider); }
long IConvertible.ToInt64(IFormatProvider provider) { return Convertible.ToInt64(provider); }
sbyte IConvertible.ToSByte(IFormatProvider provider) { return Convertible.ToSByte(provider); }
float IConvertible.ToSingle(IFormatProvider provider) { return Convertible.ToSingle(provider); }
ushort IConvertible.ToUInt16(IFormatProvider provider) { return Convertible.ToUInt16(provider); }
uint IConvertible.ToUInt32(IFormatProvider provider) { return Convertible.ToUInt32(provider); }
ulong IConvertible.ToUInt64(IFormatProvider provider) { return Convertible.ToUInt64(provider); }
object IConvertible.ToType(Type conversionType, IFormatProvider provider) { return Convertible.ToType(conversionType, provider); }
#endregion
#region IComparable<bool> Members
public int CompareTo(BOOL other) { return Value.CompareTo(other.Value); }
public int CompareTo(bool other) { return Value.CompareTo(other); }
#endregion
#region IEquatable<bool> Members
public bool Equals(BOOL other) { return Value.Equals(other.Value); }
public bool Equals(bool other) { return Value.Equals(other); }
#endregion
#region Object Override
public override string ToString() { return Value.ToString(); }
public override int GetHashCode() { return Value.GetHashCode(); }
public override bool Equals(object obj) { return Value.Equals(obj); }
#endregion
#region implicit/explicit cast operators
public static implicit operator bool(BOOL value) { return value.Value; }
public static implicit operator BOOL(bool value) { return new BOOL(value); }
public static explicit operator int(BOOL value) { return unchecked((int)value._data); }
public static explicit operator BOOL(int value) { return new BOOL(value); }
public static explicit operator uint(BOOL value) { return value._data; }
public static explicit operator BOOL(uint value) { return new BOOL(value); }
#endregion
#region +, -, !, ~, ++, --, true, false unary operators overloaded.
public static BOOL operator !(BOOL b) { return new BOOL(!b.Value); }
public static bool operator true(BOOL b) { return b.Value; }
public static bool operator false(BOOL b) { return !b.Value; }
#endregion
#region +, -, *, /, %, &, |, ^, <<, >> binary operators overloaded.
public static BOOL operator &(BOOL b1, BOOL b2) { return new BOOL(b1.Value & b2.Value); }
public static BOOL operator |(BOOL b1, BOOL b2) { return new BOOL(b1.Value | b2.Value); }
#endregion
#region ==, !=, <, >, <=, >= comparison operators overloaded
public static bool operator ==(BOOL b1, BOOL b2) { return (b1.Value == b2.Value); }
public static bool operator !=(BOOL b1, BOOL b2) { return (b1.Value != b2.Value); }
#endregion
}