The enum I've created looks like this:
enum MonthOfTheYear : byte
{
January,
February,
March,
April,
May,
June,
July = 0,
August,
September,
October,
November,
December
}
As you can see, July has an initializer of 0.
This has some interesting (side) effects: there seems to be "pairing" of integer values. February ànd August now have values of 1, March ànd September have 2 etc.:
MonthOfTheYear theMonth = MonthOfTheYear.February;
Console.WriteLine(theMonth + " has integer value of " + (int)theMonth);
and
MonthOfTheYear theMonth = MonthOfTheYear.August;
Console.WriteLine(theMonth + " has integer value of " + (int)theMonth);
clearly show this. So far, weird as I find that, I'm willing to go along.
EDIT: I get that assigning July 0 makes the indices start over. I DON'T get why they can co-exist within the same enum.
BUT! IF I then loop through the enum and output all the underlying integer values, weirdness ensues.
MonthOfTheYear theMonth = MonthOfTheYear.January;
for (int i = 0; i < 12; i++)
{
Console.WriteLine(theMonth + " has integer value of " + (int)theMonth++);
}
outputs
July has integer value of 0
February has integer value of 1
September has integer value of 2
April has integer value of 3
May has integer value of 4
June has integer value of 5
6 has integer value of 6
7 has integer value of 7
8 has integer value of 8
9 has integer value of 9
10 has integer value of 10
11 has integer value of 11
I was hoping someone could explain to me what's going on behind the scenes, because the integer values are successive, so I'm thinking this is outputting as expected but I'm not seeing it as of yet.
Firstly, when you specify a value in the definition of an enum, subsequent values number consecutively from there - and even if you specify 0 somewhere, the first value will start numbering from 0. Thus your underlying byte values are:
enum MonthOfTheYear : byte
{
January = 0, // not specified, so starts at 0
February = 1,
March = 2,
April = 3,
May = 4,
June = 5,
July = 0, // specified, so starts numbering from 0 again
August = 1,
September = 2,
October = 3,
November = 4,
December = 5
}
When you increment an enum value with ++, it just increments the underlying byte - it doesn't look at the definition of the enum and go to the element on the next line!
If this byte doesn't have a corresponding defined entry, that doesn't mean it's invalid at all - just that, when you convert the enum value to a string, you get the byte value as a string.
If the byte has several corresponding defined entries... Actually, I'm not sure exactly which entry converting it to a string will give you, but it's clearly not necessarily the first one.
Basically MonthOfTheYear.February == MonthOfTheYear.August so whether you're calling ToString on it or just looking at it in the debugger, there's no guarantee that one won't get switched for the other.
http://msdn.microsoft.com/en-us/library/system.enum.getname.aspx
If multiple enumeration members have the same underlying value, the
GetName method guarantees that it will return the name of one of those
enumeration members. However, it does not guarantee that it will
always return the name of the same enumeration member. As a result,
when multiple enumeration members have the same value, your
application code should never depend on the method returning a
particular member's name.
So, to sum it up, when you have multiple members with the same value, the name you get for a particular value is any of the members with that value.
Use the method
Enum.GetName
Here is an example:
using System;
public class GetNameTest {
enum Colors { Red, Green, Blue, Yellow };
enum Styles { Plaid, Striped, Tartan, Corduroy };
public static void Main() {
Console.WriteLine("The 4th value of the Colors Enum is {0}", Enum.GetName(typeof(Colors), 3));
Console.WriteLine("The 4th value of the Styles Enum is {0}", Enum.GetName(typeof(Styles), 3));
}
}
// The example displays the following output:
// The 4th value of the Colors Enum is Yellow
//
You get an full explanation here:
http://msdn.microsoft.com/de-de/library/system.enum.getname.aspx
You explicitly set july to be the first month in the enum. This messes things up.
Try this:
enum MonthOfTheYear : byte {
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
}
for (int i = 0; i < 12; i++) {
Console.WriteLine(String.Format("{0} has integer value of {1}", Enum.GetName(typeof(MonthOfTheYear), i), i));
}
Because you set july to zero it resets the indexer from that point. If you want this strange order to be in place, consider rearranging the order in your enum.
Related
Is there some way to automatically loopback when the value of an Enumeration reaches the end while adding or subtracting values.
E.g. When using DateTime.DayOfWeek it is defined as:
public enum DayOfWeek
{
Sunday = 0,
Monday = 1,
Tuesday = 2,
Wednesday = 3,
Thursday = 4,
Friday = 5,
Saturday = 6,
}
I have a function where I'm checking if a string array contains yesterday.
DateTime rn = DateTime.Now;
string[] daysOfWeek = {"Monday", "Tuesday", "Saturday"};
if (daysOfWeek.Contains((rn.DayOfWeek - 1).ToString()))
...
If today is Sunday. Is there some way to make the rn.DayOfWeek enumeration to loop back around the beginning to Saturday in this case?
Similarly if I'm adding instead of subtracting, can one somehow loop around the end from Saturday (6) back to Sunday (0)?
You shouldn't be adding/subtracting when dealing with enums. That is dangerous ground. Instead, you should be adding/subtracting days to your DateTime:
string today = DateTime.Now.DayOfWeek.ToString();
string tomorrow = DateTime.Now.AddDays(1).DayOfWeek.ToString();
string yesterday = DateTime.Now.AddDays(-1).DayOfWeek.ToString();
I guess in this particular case it could be
DateTime rn = DateTime.Now.AddDays(5);
string[] daysOfWeek = { "Monday", "Tuesday", "Saturday" };
if (daysOfWeek.Contains(((rn.DayOfWeek) == 0 ? rn.DayOfWeek + 6 : rn.DayOfWeek - 1).ToString()))
Console.WriteLine("Found");
Although I agree that such code generally should not be used.
You cannot have an automatic "looping" behavior on random enumerations, however, there are some ways you could handle your problem.
Most of the time, you could simply use the % operator, which in the case of DayOfWeek would amount to something like this:
// Prints Friday
Console.WriteLine((DayOfWeek)(((int)DayOfWeek.Saturday + 6) % 7));
You could also write an extension method like this one:
public static class DateTimeExtensions
{
public static DayOfWeek AddDays(this DayOfWeek dayOfWeek, int count)
{
if (dayOfWeek < 0 || (int)dayOfWeek > 6) throw new ArgumentOutOfRangeException();
int adjustedValue = ((int)dayOfWeek + count) % 7;
return (DayOfWeek)(adjustedValue < 0 ? adjustedValue + 7 : adjustedValue);
}
}
With this extension method, you could do something like this:
Console.WriteLine(DayOfWeek.Sunday.AddDays(-1)); // Prints "Saturday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(1)); // Prints "Monday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(7)); // Prints "Sunday"
Console.WriteLine(DayOfWeek.Sunday.AddDays(-7)); // Prints "Sunday"
There's no built in way to do this but if you're happy working with integers then it's pretty easy, you just want to remap all your values from -X to +X into the 0-6 range so for a positive value you'd do
value+1 (to remap to 1-7 range since we're going to divide by 7) %7 (this gives you the remainder of the division by 7, so 1%7 = 1 8 = 1 etc etc, you've got it looping every 7 days) -1 (to remap out 1-7 range to your 0-6 enum value) and cast that as your enum.
Now we just need to consider negative value and convert the negative value into something positive first before passing it into our previous function. In this case we want to map the oposite days (-1 is the same as +6, one day before the start of the week is 6 days after the end of the week etc), so if your value is negative you want to do abs(value) to make it positive and the substract it from 7 to remap it into the positive range
Here's some code (untested)
if(value < 0)
{
value = 7 - Math.Abs(value)
}
value++; (remap 0-6 to 1-7)
value = value % 7; (remap 1 - int.maxvalue to 1-7)
value--; (remap 1-7 to 0-6;
And now value contains the number that maps to your enum.
You can create a following extension method (can easily be changed for string arrays).
public static bool ContainsYesterday(this DayOfWeek[] days)
{
return days.Contains(DateTime.Now.AddDays(-1).DayOfWeek);
}
edited as previous version had a bug specified in comment.
I have the following array:
double[] list = new double[] {0,0,100,100}
Why if I search for 29.6 I get -3?
Array.BinarySearch(list, 29.6)
I expected +1 or -1.
The Array.BinarySearch() documentation for the return parameter says:
The index of the specified value in the specified array, if value is found. If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value. If value is not found and value is greater than any of the elements in array, a negative number which is the bitwise complement of (the index of the last element plus 1).
But it does not says too much to me.
If value is not found and value is less than one or more elements in array, a negative number which is the bitwise complement of the index of the first element that is larger than value.
The first element which is larger than 29.6 is 100, which has index of 2.
~2 is -3.
You can use the '~' to take the bitwise complement which will give you the index of the first item larger than the search item.
If the Array does not contain the specified value, the method returns
a negative integer. You can apply the bitwise complement operator (~)
to the negative result (in Visual Basic, Xor the negative result with
-1) to produce an index. If this index is greater than or equal to the size of the array, there are no elements larger than value in the
array. Otherwise, it is the index of the first element that is larger
than value.
From the MSDN
Thus if you had:
var pos = Array.BinarySearch(list, 29.6);
You can check:
if (pos < 0)
{
Console.WriteLine("Not found, the result was {0} which is index {1}", pos, ~pos);
}
Which, in your case, means your -3 would indicate the index 2 is the first item larger than your search target.
Here is your answer:
"a negative number which is the bitwise complement of the index of the first element that is larger than value."
So in your case, your searched value (29.6) is less then 100 which is the 3rd element in your array list, the complement of 3 is -3, which is the answer you got.
Here I extended your example and created another array list (list2) with some different values then I searched same value like you 29.6, now this 29.6 value is smaller then 100 but greater then 25, and in my array list 100 is on position 4 and its complement is -4.
So I get the result -4, if I have searched 20 in my array list I would have get answer -3.
double[] list = new double[] { 0, 0, 100, 100 };
double[] list2 = new double[] { 10, 15, 25, 100 };
int result = Array.BinarySearch(list, 29.6);
int result2 = Array.BinarySearch(list2, 29.6);
Response.Write("Your answer result:" + result.ToString() + "<br/>");
Response.Write("Your answer result2:" + result2.ToString());
My Code result:
Your answer result : -3
Your answer result2: -4
I hope this helps.
I need some input.
Say you have an int-based Enum with values 1 through 10. If you then have a variable that is, say, value corresponding to 7, how can you easiest set it to next value in the given range without going out of bounds? If the value reaches the limit, it should reset itself to first in the range.
I want a one-liner solution to this. I don't want to do ++ and then check and reset value, plus it has to work in both C# and JavaScript. I suppose something in the Math object might be of help, I don't know...
thanks
Increment, subtract 1, then modulo, then add 1 (since your Enum is 1-based).
((++i - 1) % N + 1
(N=10, the maximum value your Enum can take on.)
If you know the limits and are sure that all numbers between 0 and that upper limit is occupied by an enum you can use the modulo operator
myEnum = (myEnum + 1) % maxValue;
You may need to typecast:
myEnum = (MyEnumType) (((int) myEnum + 1) % maxValue);
EDIT: I noticed you have one-based enums. If you really need this, then you would have to do as larsman suggests in his answer:
// This statement may look weird, but it works :)
myEnum = (myEnum % maxValue) + 1
// Produces (for myEnum with maxValue set to 4, i.e. allows 1,2,3 & 4 as valid values):
// 1 => 2
// 2 => 3
// 3 => 4
// 4 => 1
I'm working on an app that sends raw data to zebra printer and print out barcodes. And since every item has its own unique barcode, I need to define a variable that automatically generates unique number of 12 digits long.
see example:
printBar prnt = new printBar("123456789012");
Is there anyway to define a double variable and pass it to a function that return uniqely 12 digits number and pass it over again to the printBar class?. But how to make sure everytime you access it returns a unique value?.
I also thought of another way, since am using MS Access db, I can create a column of AutoNumber datatype and assign it to Random, but you don't get the exact 12 digits required, sometimes it generates a value of 10 digits sometimes more or less.
Start with a twelve digit number, ie: 111111111111
to get your new 'random' unique number take the previous number and add 1.
although not random, it will guarantee uniqueness.
How many times do you generate a new barcode per day, hour, minute?
You could use a technique like the auto versioning of Visual Studio works.
Count the number of days from some specific date (e.g. 1.1.2000)
padded with 0 to five places.
Concat the seconds elapsed till midnight
padded also with zero to five places.
Fill up the last two numbers with a static counter in your App that just wrap around at 99.
Example
public static class UniqueId
{
static private int _InternalCounter = 0;
static public string Get()
{
var now = DateTime.Now;
var days = (int)(now - new DateTime(2000, 1, 1)).TotalDays;
var seconds = (int)(now - DateTime.Today).TotalSeconds;
var counter = _InternalCounter++ % 100;
return days.ToString("00000") + seconds.ToString("00000") + counter.ToString("00");
}
With this approach you'll get an overflow at the 15. October 2273, but i think this can be solved by your follower. ;-)
If you need to create more than hundred unique IDs per second you can change the last two line into:
var counter = _InternalCounter++ % 1000;
return days.ToString("0000") + seconds.ToString("00000") + counter.ToString("000");
Now you'll have thousand unique IDs per second, but the days will already overflow at 18. May 2027. If this is too short, you can get additional ten years if you set the start date to 2010 by this line:
var days = (int)(now - new DateTime(2010, 1, 1)).TotalDays;
Using an RNG and a hash do:
10 - stream out 12 digits
20 - check if value is in hash
30 - if it's goto 40 else goto 10
40 - push value into hash
50 - return new 12 digit number
60 - goto 10
Is there a way to write binary literals in C#, like prefixing hexadecimal with 0x? 0b doesn't work.
If not, what is an easy way to do it? Some kind of string conversion?
Update
C# 7.0 now has binary literals, which is awesome.
[Flags]
enum Days
{
None = 0,
Sunday = 0b0000001,
Monday = 0b0000010, // 2
Tuesday = 0b0000100, // 4
Wednesday = 0b0001000, // 8
Thursday = 0b0010000, // 16
Friday = 0b0100000, // etc.
Saturday = 0b1000000,
Weekend = Saturday | Sunday,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}
Original Post
Since the topic seems to have turned to declaring bit-based flag values in enums, I thought it would be worth pointing out a handy trick for this sort of thing. The left-shift operator (<<) will allow you to push a bit to a specific binary position. Combine that with the ability to declare enum values in terms of other values in the same class, and you have a very easy-to-read declarative syntax for bit flag enums.
[Flags]
enum Days
{
None = 0,
Sunday = 1,
Monday = 1 << 1, // 2
Tuesday = 1 << 2, // 4
Wednesday = 1 << 3, // 8
Thursday = 1 << 4, // 16
Friday = 1 << 5, // etc.
Saturday = 1 << 6,
Weekend = Saturday | Sunday,
Weekdays = Monday | Tuesday | Wednesday | Thursday | Friday
}
C# 7.0 supports binary literals (and optional digit separators via underscore characters).
An example:
int myValue = 0b0010_0110_0000_0011;
You can also find more information on the Roslyn GitHub page.
Only integer and hex directly, I'm afraid (ECMA 334v4):
9.4.4.2 Integer literals Integer literals are used to write values of
types int, uint, long, and ulong.
Integer literals have two possible
forms: decimal and hexadecimal.
To parse, you can use:
int i = Convert.ToInt32("01101101", 2);
Adding to #StriplingWarrior's answer about bit flags in enums, there's an easy convention you can use in hexadecimal for counting upwards through the bit shifts. Use the sequence 1-2-4-8, move one column to the left, and repeat.
[Flags]
enum Scenery
{
Trees = 0x001, // 000000000001
Grass = 0x002, // 000000000010
Flowers = 0x004, // 000000000100
Cactus = 0x008, // 000000001000
Birds = 0x010, // 000000010000
Bushes = 0x020, // 000000100000
Shrubs = 0x040, // 000001000000
Trails = 0x080, // 000010000000
Ferns = 0x100, // 000100000000
Rocks = 0x200, // 001000000000
Animals = 0x400, // 010000000000
Moss = 0x800, // 100000000000
}
Scan down starting with the right column and notice the pattern 1-2-4-8 (shift) 1-2-4-8 (shift) ...
To answer the original question, I second #Sahuagin's suggestion to use hexadecimal literals. If you're working with binary numbers often enough for this to be a concern, it's worth your while to get the hang of hexadecimal.
If you need to see binary numbers in source code, I suggest adding comments with binary literals like I have above.
You can always create quasi-literals, constants which contain the value you are after:
const int b001 = 1;
const int b010 = 2;
const int b011 = 3;
// etc ...
Debug.Assert((b001 | b010) == b011);
If you use them often then you can wrap them in a static class for re-use.
However, slightliy off-topic, if you have any semantics associated with the bits (known at compile time) I would suggest using an Enum instead:
enum Flags
{
First = 0,
Second = 1,
Third = 2,
SecondAndThird = 3
}
// later ...
Debug.Assert((Flags.Second | Flags.Third) == Flags.SecondAndThird);
If you look at the language feature implementation status of the .NET Compiler Platform ("Roslyn") you can clearly see that in C# 6.0 this is a planned feature, so in the next release we can do it in the usual way.
string sTable="static class BinaryTable\r\n{";
string stemp = "";
for (int i = 0; i < 256; i++)
{
stemp = System.Convert.ToString(i, 2);
while(stemp.Length<8) stemp = "0" + stemp;
sTable += "\tconst char nb" + stemp + "=" + i.ToString() + ";\r\n";
}
sTable += "}";
Clipboard.Clear();
Clipboard.SetText ( sTable);
MessageBox.Show(sTable);
Using this, for 8bit binary, I use this to make a static class and it puts it into the clipboard.. Then it gets pasted into the project and added to the Using section, so anything with nb001010 is taken out of a table, at least static, but still...
I use C# for a lot of PIC graphics coding and use 0b101010 a lot in Hi-Tech C
--sample from code outpt--
static class BinaryTable
{ const char nb00000000=0;
const char nb00000001=1;
const char nb00000010=2;
const char nb00000011=3;
const char nb00000100=4;
//etc, etc, etc, etc, etc, etc, etc,
}
:-)
NEAL
Binary literal feature was not implemented in C# 6.0 & Visual Studio 2015. but on 30-March 2016 Microsoft announced the new version of Visual Studio '15' Preview with that we can use binary literals.
We can use one or more than one Underscore( _ ) character for digit separators. so the code snippet would look something like:
int x = 0b10___10_0__________________00; //binary value of 80
int SeventyFive = 0B100_________1011; //binary value of 75
WriteLine($" {x} \n {SeventyFive}");
and we can use either of 0b and 0B as shown in the above code snippet.
if you do not want to use digit separator you can use it without digit separator like below code snippet
int x = 0b1010000; //binary value of 80
int SeventyFive = 0B1001011; //binary value of 75
WriteLine($" {x} \n {SeventyFive}");
While not possible using a Literal, maybe a BitConverter can also be a solution?
Though the string parsing solution is the most popular, I don't like it, because parsing string can be a great performance hit in some situations.
When there is needed a kind of a bitfield or binary mask, I'd rather write it like
long bitMask = 1011001;
And later
int bit5 = BitField.GetBit(bitMask, 5);
Or
bool flag5 = BitField.GetFlag(bitMask, 5);`
Where BitField class is
public static class BitField
{
public static int GetBit(int bitField, int index)
{
return (bitField / (int)Math.Pow(10, index)) % 10;
}
public static bool GetFlag(int bitField, int index)
{
return GetBit(bitField, index) == 1;
}
}
You can use 0b000001 since Visual Studio 2017 (C# 7.0)
Basically, I think the answer is NO, there is no easy way. Use decimal or hexadecimal constants - they are simple and clear. #RoyTinkers answer is also good - use a comment.
int someHexFlag = 0x010; // 000000010000
int someDecFlag = 8; // 000000001000
The others answers here present several useful work-a rounds, but I think they aren't better then the simple answer. C# language designers probably considered a '0b' prefix unnecessary. HEX is easy to convert to binary, and most programmers are going to have to know the DEC equivalents of 0-8 anyways.
Also, when examining values in the debugger, they will be displayed has HEX or DEC.