In C#, if we define an enum that contains a member correspondingto a negative value, and then we iterate over that enum's values, the negative value does not come first, but last. Why does that happen? In other languages (C, C++, Ada, etc), iterating over an enum will give you the order in which you defined it.
MSDN has a good example of this behavior:
using System;
enum SignMagnitude { Negative = -1, Zero = 0, Positive = 1 };
public class Example
{
public static void Main()
{
foreach (var value in Enum.GetValues(typeof(SignMagnitude)))
{
Console.WriteLine("{0,3} 0x{0:X8} {1}",
(int) value, ((SignMagnitude) value));
}
}
}
// The example displays the following output:
// 0 0x00000000 Zero
// 1 0x00000001 Positive
// -1 0xFFFFFFFF Negative
From the very documentation page you link to, my emphasis:
The elements of the array are sorted by the binary values of the enumeration constants (that is, by their unsigned magnitude).
Digging into the CLR code (the 2.0 SSCLI) and getting far lower-level than I'm really comfortable with, it looks like ultimately this is because internally enum values are stored in something that looks like this (note this is C++):
class EnumEEClass : public EEClass
{
friend class EEClass;
private:
DWORD m_countPlusOne; // biased by 1 so zero can be used as uninit flag
union
{
void *m_values;
BYTE *m_byteValues;
USHORT *m_shortValues;
UINT *m_intValues;
UINT64 *m_longValues;
};
LPCUTF8 *m_names;
As can be seen, it's unsigned types that hold the actual values - so when these values are emitted for enumeration, naturally they are in their unsigned order.
Related
If you run the following code:
SByte w = -5;
Console.WriteLine(w.CompareTo(0));
Int32 x = -5;
Console.WriteLine(x.CompareTo(0));
SByte y = 5;
Console.WriteLine(y.CompareTo(0));
Int32 z = 5;
Console.WriteLine(z.CompareTo(0));
then you get the following output:
-5
-1
5
1
Why do these methods with the same name that have almost identical descriptions in the MSDN documentation behave so differently?
Because the SByte.CompareTo() is implemented like
return m_value - value;
so a simple subtraction. This works because the m_value is converted automatically to int, and any possibile combination of values is "legal" with int.
With two Int32 this can't be done, because for example Int32.MinValue.CompareTo(Int32.MaxValue) would become Int32.MinValue - Int32.MaxValue that would be outside the int range, and in fact it is implemented as two comparisons:
if (m_value < value) return -1;
if (m_value > value) return 1;
return 0;
in general
The only important "thing" of the returned value of a CompareTo is its sign (or if it is 0). The "value" is irrelevant. The return value of 1, 5, 500, 5000, 5000000 of CompareTo() are the same. CompareTo can't be used to measure "distance" between numbers. So both implementations are equivalent.
It is totally wrong to do:
if (someValue.CompareTo(someOtherValue) == -1)
you must always
if (someValue.CompareTo(someOtherValue) < 0)
why the SByte.CompareTo is built that way
SByte.CompareTo is implementing a "branchless" comparison (there are no ifs in the code, the flow of code is linear). Processors have problems with branches, so branchless code could be faster than "branchful" code, so this microoptimization. Clearly SByte.CompareTo could have been written as Int32.CompareTo.
why any negative value is equivalent to -1 (and any positive value is equivalent to +1)
This is probably something that is derived directly from the C language: the qsort function for example to compare items uses a user-defined method that is like:
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements. It shall follow the following prototype:
int compar (const void* p1, const void* p2);
Taking two pointers as arguments (both converted to const void*). The function defines the order of the elements by returning (in a stable and transitive manner):
return value meaning
<0 The element pointed to by p1 goes before the element pointed to by p2
0 The element pointed to by p1 is equivalent to the element pointed to by p2
>0 The element pointed to by p1 goes after the element pointed to by p2
how is the .CompareTo implemented in other primitive types?
SByte, Byte, Int16, UInt16, Char all use the subtraction "method", while Int32, UInt32, Int64, UInt64 all use the if "method".
Looking at the source for these two methods, they are implemented differently:
public int CompareTo(sbyte value)
{
return (int)(this - value);
}
vs
public int CompareTo(int value)
{
if (this < value)
{
return -1;
}
if (this > value)
{
return 1;
}
return 0;
}
But none of this matters, since the sign of the returned value is the only thing that you should be checking.
I'm working with pulling a stream of bytes off of a medical device, and have run into a really annoying data structure. Basically, I am getting back a 2-byte chunk where each bit represents a boolean value. This structure appears frequently enough in the byte stream to develop a struct/class around it, but in each instance, the bits mean completely different things.
So first I set up a bunch of Enums to represent all the different definitions the bit structure could have. (Note that not every bit is used in every definition. Sometimes there are breaks in between the important bits.)
EDIT: Removed all names that looked like 'flag.' I'm not using the [Flags] attribute, and this seems to be a point of contention/confusion. The enum values are simply mapped to the indices in my BitArray.
public enum RecordInfo { AM_TEST = 0, PM_TEST, TEST_VALIDITY };
public enum RecordAlerts { ALERT1 = 0, ALERT2, ALERT3, ALERT4, VALIDATED = 15 };
Then created this container to hold the actual bits:
public struct TwoBytes<TEnum> where TEnum : struct, IConvertible
{
private BitArray _bits = new BitArray(2);
}
This seems to work as I need, until I want to index my structure based on an Enum name. So say I have a TwoByte struct called Alerts, and this contains some bit values. If I want to get a specific flag like this:
bool alert3Set = Alerts[RecordAlerts.ALERT3]
I end up with a truly heinous index function. This is what I have in place now:
public bool this[TEnum name]
{
get
{
int index = Enum.GetValues(typeof(TEnum)).Cast<TEnum>().ToList().Where(x => x.Equals(name)).Cast<int>().First();
return _bits[index];
}
}
Now it works, crazily enough. But that LINQ chains looks positively atrocious, and it takes a while to decipher what it's actually doing.
Is there a cleaner, more efficient way of converting a generic Enum 'name' to its integer value? Or would I be better suited to use a Dictionary (or some other object) to represent the bit structure definitions?
As long as every TEnum you'd use derives from int (the default), and not from another number type, this will work:
public bool this[TEnum name]
{
get
{
int index = (int)(object)name;
return _bits[index];
}
}
If you want to support enums derived from smaller types (and enums that only use values within the range supported by int), I'd use:
public bool this[TEnum name]
{
get
{
int index = Convert.ToInt32(name);
return _bits[index];
}
}
(fully supporting enums derived from types that can't implicitly be converted to int, like uint, long, and ulong, gets more complicated, because BitArray's indexer uses an int)
I think a bit of OOP would make your life easier. You can introduces classes that represent the data you receive, and has meaningful property names. Each class could accept your BitArray into constructor and parse it into properties.
Further in your program you could use these classes instead of fiddling with bits.
As FrankPI suggested in the comments, why not use an enum whose values really represent each bit, rather than using an intermediate BitArray?
[Flags]
public enum RecordFlags { FLAG1 = 0x1, FLAG2 = 0x2, FLAG3 = 0x4, FLAG4 = 0x8, FLAG5 = 0x10, VALIDATED = 0x8000 };
var readFlags = (RecordFlags) ((bytes[0] << 8) | bytes[1]);
bool hasFlag2 = (readFlags & RecordFlags.Flag2) != 0;
In my application, I have something like:
public enum Locations {
LocationA,
LocationB,
LocationC
}
private List<Locations> _myLocations;
public Int64 PackedLocations {
get {
return PackEnumList(this._myLocations);
}
}
So: an enum (backed by int), a List of those enum values, and a read-only property which returns the result of a method I've left out so far.
That method, PackEnumList, is meant to give me a 64-bit integer where each BIT denotes whether the corresponding enum value was selected or not in a list of unique enum values. So in my example above, if _myLocations has only one item: {Locations.LocationA}, the result would be 1 (binary: ...00001), if we then add Locations.LocationC to that list, the result would be 5 (binary: ...000101). The implementation isn't important right now (but I'll include it below for completion/interest/feedback), but the signature of that method is:
public Int64 PackEnumList(List<Enum> listOfEnumValues) {
...
}
When I compile, I get an error that "the best overloaded method ... has some invalid arguments".
I'm guessing this is because _myLocations is being seen as a List of int values, but I'd like PackEnumList() to work even if the enumeration being used were backed by something else, if possible.
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
For completeness, here's the rest of what I'm trying to do (these are static because they're in a shared utility class). These are completely untested yet (since I can't get past the compile error when calling the pack method), so take them with a grain of salt. And there might be a better way to do this, I'm doing this half to solve an interesting problem, and half because I think it is an interesting problem.
public static Int64 PackEnumList(List<Enum> listOfEnumValues) {
BitArray bits = new BitArray(64, defaultValue: false);
foreach (var value in listOfEnumValues) {
// get integer value of each Enum in the List:
int val = Convert.ToInt32(value);
if (val >= 64) {
// this enum has more options than we have bits, so cannot pack
throw new Exception("Enum value out of range for packing: " + val.ToString());
}
bits[val] = true;
}
var res = new Int64[1];
bits.CopyTo(res, 0);
return res[0];
}
// (this method is a little farther from the ideal: the resulting list will need
// to be matched by the caller to the appropriate List of Enums by casting
// each Int32 value to the Enum object in the list)
public static List<Int32> UnpackEnumList(Int64 packedValue) {
string binaryString = Convert.ToString(packedValue, 2);
List<Int32> res = new List<Int32>();
for (int pos = 0; pos < binaryString.Length; pos++) {
if (binaryString[binaryString.Length - pos - 1] == '1') {
// bit is on
res.Add(pos);
}
}
return res;
}
Is there a more appropriate way to make a method which will accept a List/Collection of any enumeration?
Within straight C#? Nope. But you can fudge it...
I have a project called Unconstrained Melody which allows you to make a generic method with a constraint of "T must be an enum type" or "T must be a delegate type". These are valid constraints at the IL level, but can't be expressed in C#
Basically Unconstrained Melody consists of two parts:
A library of useful methods with those constraints, where the source code is written using valid C# which doesn't actually represent those constraints, but uses a marker interface
An IL-rewriting project (ugly but servicable) which converts those constraints into the real "unspeakable" ones
(The expectation is that users of the library would just use the rewritten binary.)
It sounds like you could use the latter part of the project for your code here. It won't be terribly pleasant, but it would work. You might also find the library part useful.
As a side thought, you might want to consider using a [Flags]-style enum instead:
[Flags]
public enum Locations {
LocationA = 1 << 0,
LocationB = 1 << 1,
LocationC = 1 << 2
}
Change your method signature to public Int64 PackEnumList(IEnumerable<Enum> listOfEnumValues)
And then call it like following:
public Int64 PackedLocations
{
get { return PackEnumList(this._myLocations.Cast<Enum>()); }
}
A List<Enum> is not a List<Locations> nor a List<Int32>. Use a generic method to handle the list:
public static void PackEnumList<T>(IEnumerable<T> list) where T : IConvertible
{
foreach (var value in list)
int numeric = value.ToInt32();
// etc.
}
I'd change your signature method to:
public Int64 PackEnumList<T>(IEnumerable<T> listOfEnumValues) where T : struct, IFormattable, IConvertible {
...
}
The where T : struct... constrains it to enum types only (any any other struct implementing both interfaces, which is probably very low)
Expanding on Jon Skeet's answer to This Previous Question. Skeet doesn't address the failure that occurs when negative values and two's complement values enter the picture.
In short, I want to convert any simple type (held in an unknown boxed object) to System.UInt64 so I can work with the underlying binary representation.
Why do I want to do this? See the explanation at the bottom.
The example below shows the cases where Convert.ToInt64(object) and Convert.ToUInt64(object) both break (OverflowException).
There are only two causes for the OverflowExceptions below:
-10UL causes an exception when converting to Int64 because the negative value casts to 0xfffffffffffffff6 (in the unchecked context), which is a positive number larger than Int64.MaxValue. I want this to convert to -10L.
When converting to UInt64, signed types holding negative values cause an exception because -10 is less than UInt64.MinValue. I want these to convert to their true two's complement value (which is 0xffffffffffffffff6). Unsigned types don't truly hold the negative value -10 because it is converted to two's complement in the unchecked context; thus, no exception occurs with unsigned types.
The kludge solution would seem to be conversion to Int64 followed by an unchecked cast to UInt64. This intermediate cast would be easier because only one instance causes an exception for Int64 versus eight failures when converting directly to UInt64.
Note: The example uses an unchecked context only for the purpose of forcing negative values into unsigned types during boxing (which creates a positive two's complement equivalent value). This unchecked context is not a part of the problem at hand.
using System;
enum DumbEnum { Negative = -10, Positive = 10 };
class Test
{
static void Main()
{
unchecked
{
Check((sbyte)10);
Check((byte)10);
Check((short)10);
Check((ushort)10);
Check((int)10);
Check((uint)10);
Check((long)10);
Check((ulong)10);
Check((char)'\u000a');
Check((float)10.1);
Check((double)10.1);
Check((bool)true);
Check((decimal)10);
Check((DumbEnum)DumbEnum.Positive);
Check((sbyte)-10);
Check((byte)-10);
Check((short)-10);
Check((ushort)-10);
Check((int)-10);
Check((uint)-10);
Check((long)-10);
//Check((ulong)-10); // OverflowException
Check((float)-10);
Check((double)-10);
Check((bool)false);
Check((decimal)-10);
Check((DumbEnum)DumbEnum.Negative);
CheckU((sbyte)10);
CheckU((byte)10);
CheckU((short)10);
CheckU((ushort)10);
CheckU((int)10);
CheckU((uint)10);
CheckU((long)10);
CheckU((ulong)10);
CheckU((char)'\u000a');
CheckU((float)10.1);
CheckU((double)10.1);
CheckU((bool)true);
CheckU((decimal)10);
CheckU((DumbEnum)DumbEnum.Positive);
//CheckU((sbyte)-10); // OverflowException
CheckU((byte)-10);
//CheckU((short)-10); // OverflowException
CheckU((ushort)-10);
//CheckU((int)-10); // OverflowException
CheckU((uint)-10);
//CheckU((long)-10); // OverflowException
CheckU((ulong)-10);
//CheckU((float)-10.1); // OverflowException
//CheckU((double)-10.1); // OverflowException
CheckU((bool)false);
//CheckU((decimal)-10); // OverflowException
//CheckU((DumbEnum)DumbEnum.Negative); // OverflowException
}
}
static void Check(object o)
{
Console.WriteLine("Type {0} converted to Int64: {1}",
o.GetType().Name, Convert.ToInt64(o));
}
static void CheckU(object o)
{
Console.WriteLine("Type {0} converted to UInt64: {1}",
o.GetType().Name, Convert.ToUInt64(o));
}
}
WHY?
Why do I want to be able to convert all these value types to and from UInt64? Because I have written a class library that converts structs or classes to bit fields packed into a single UInt64 value.
Example: Consider the DiffServ field in every IP packet header, which is composed of a number of binary bit fields:
Using my class library, I can create a struct to represent the DiffServ field. I created a BitFieldAttribute which indicates which bits belong where in the binary representation:
struct DiffServ : IBitField
{
[BitField(3,0)]
public PrecedenceLevel Precedence;
[BitField(1,3)]
public bool Delay;
[BitField(1,4)]
public bool Throughput;
[BitField(1,5)]
public bool Reliability;
[BitField(1,6)]
public bool MonetaryCost;
}
enum PrecedenceLevel
{
Routine, Priority, Immediate, Flash, FlashOverride, CriticEcp,
InternetworkControl, NetworkControl
}
My class library can then convert an instance of this struct to and from its proper binary representation:
// Create an arbitrary DiffServe instance.
DiffServ ds = new DiffServ();
ds.Precedence = PrecedenceLevel.Immediate;
ds.Throughput = true;
ds.Reliability = true;
// Convert struct to value.
long dsValue = ds.Pack();
// Create struct from value.
DiffServ ds2 = Unpack<DiffServ>(0x66);
To accomplish this, my class library looks for fields/properties decorated with the BitFieldAttribute. Getting and setting members retrieves an object containing the boxed value type (int, bool, enum, etc.) Therefore, I need to unbox any value type and convert it to it's bare-bones binary representation so that the bits can be extracted and packed into a UInt64 value.
I'm going to post my best solution as fodder for the masses.
These conversions eliminate all exceptions (except for very large float, double, decimal values which do not fit in 64-bit integers) when unboxing an unknown simple value type held in object o:
long l = o is ulong ? (long)(ulong)o : Convert.ToInt64(o));
ulong u = o is ulong ? (ulong)o : (ulong)Convert.ToInt64(o));
Any improvements to this will be welcomed.
I want to create a new type, i. e:
[sbyte (1 Byte) Value-range : -128 to +127]
[byte (1 Byte) Value-range : 0 to +255]
[short (2 Byte) Value-range : -32768 to +32767]
[ushort (2 Byte) Value-range : 0 to +65535]
[int (4 Byte) Value-range : -2147483648 to +2147483647]
[uint (4 Byte) Value-range : 0 to +4294967295]
.
.
.
etc.
now I want to create LInt(LowInt) Type in range 0 to 200000, so I dont want to use uint or int.
Is it any possible with C#?
Thank You!
Yes, that is what classes are for. Now, you cannot create a new "builtin" type. The semantics may not be exactly the same, but I'm guessing you won't care too much about those differences.
It is not possible in a built-in way, using simple language, e.g. int<5000,20000>.
While it is possible with a more complex definition, it isn't easy. It is difficult to determine and define all the semantics you'd want, such as:
Conversion to other ranged types
Conversion from built in numeric types
What should happen on overflow/underflow
What should the resulting type's range be after arithmetic is performed
Such a solution also wouldn't cover cases where you'd want one parameter's type range be constrained based on another parameter's value.
An alternative would be to use something like Code Contracts to define contracts for your code so you can do arbitrary static (compile time) verifications.
Edit: Removed link to SpecSharp. It looks like it was replaced with Code Contracts...
you can also use a struct to create a "type", but you are not able to create a primitive type.
You can create an object and handle your conditions, if you want it to act more like a primitive try making it a struct
It is of no use. Your CPU architecture defines what chunks of data it can handle at once and for what purposes. Even if you created a type that only allowed for different min-max values (which you can implement in a class and operator overloading), it would not be more efficient in neither memory nor performance aspects.
If you want to simply enforce some semantics, here's something that should lead in you the right direction (it's by no means complete, and lacks support for the checked and unchecked keywords).
struct MyInt
{
static uint max = 200000;
readonly uint i;
public MyInt(uint i) {
this.i = i;
}
public static implicit operator MyInt(uint j) {
if(j > max)
throw new ArgumentException();
return new MyInt(j);
}
public static MyInt operator +(MyInt i, uint j) {
try {
return new MyInt(i.i + j);
}
catch(ArgumentException) {
throw new OverflowException();
}
}
public override string ToString ()
{
return i.ToString();
}
}