Arrays in a demo application - c#

the thing I'm having the most trouble with is understanding the assignment here. I don't know if it's the fact if it's worded weird or that I'm just stupid. I'm not asking for you to do my assignment for me I just want to know if someone would explain what it's asking for.
UPDATE: apparently I now have to use enum on this so now I'm screwed

Please post the content of the question in your post, i.e. copy and past the text.
Secondly, break it down into sections.
1) You must write a program called IntArrayDemo.
2) The program must contain an array that stores 10 Integers (int).
int[] valueArray = new int[10] {1,2,3,4,5,6,7,8,9,10 };
3) The program will run until a sentinal value is entered (i.e. you type something that causes the program to quite, say 'q' or '-1').
while (Console.ReadKey().Key != ConsoleKey.Q) {
ConsoleKey k = Console.ReadKey().Key;
//Check the key here
}
4) The program will have 3 options -
4.1) View the entire array of integers from 0 to 9 (i.e. forwards)
4.2) View the entire array of integers from 9 to 0 (i.e. backwards)
4.3) View a specific location (i.e. you enter a number from 0 to 9, and you are shown the value at that point in the array.
You will need to display some sort of menu on the screen listing the options.
For each of the parts where you need to show the content of the array, use a for loop. While loops, or ForEach loops should never be used of you have a fixed number of things to iterate over.
"I don't know if it's the fact if it's worded weird or that I'm just stupid"
In this case, I'm not sure either of those options is accurate. Programming questions are worded quite carefully to force you to think about breaking the task into sections.
In professional programming, you will get all sorts of weirdly worded questions about how something can be done, and you must break down the problem into steps and solve each one.
It's easy to feel a little overwhelmed when you get a single paragraph with a lot of information in it, but breaking it down makes it much more manageable.
Always start with what you know for certain has to be done - in this case, the program must be called IntArrayDemo, so that's a good starting point.
'that stores an array of 10 integers' - good, more information! The program must have an array, which stores ints, and can hold 10 values.
We can infer from this (knowing that arrays start from 0) that our array must count from 0 to 9.
Enums
You mention that you need to use enums. Enums are just a data type, which you can define yourself.
Supposing you were writing a server program, and needed to easily see what state it was in.
The server can be in the following states at any time - Starting, Running, Stopping, Stopped.
You could use a string easily enough - String state = "Starting" would do the trick, but a string can hold any value.
As the server HAS to be in one of those states, an enum is better, as you can specify what those states are.
To declare an enum, you create it as follows...
enum SERVER_STATE { Starting, Running, Stopping, Stopped };
Then to use it....
SERVER_STATE CurrentServerState = SERVER_STATE.Stopped;
if (CurrentServerState == SERVER_STATE.Running) {
//Do something here only if the enum is set to 'Running'
}
If you wanted to use an enum to decide which option was chosen, you would need to do the following.
1) Get some text of the keyboard (the example using ReadChar above shows you how to do that)
2) Set an enum value based on what was entered
enum ACTION = { ListValuesForward, ListValueBackward, ListSpecificValue };
ACTION WhichOption;
//Our ConsoleKey object is called 'k', so....
if (k == ConsoleKey.F) {
WhichOption = ACTION.ListValuesForward;
}
if (WhichOption == Action.ListValuesForward) {
//Print out the array forwards
}
Knowing that we have an array, that counts from 0 to 9, we can work out that the best loop here is a for loop, as it's controlled by a counter variable.
If you always break a problem down like this, it becomes a lot less daunting.
Hopefully, this should explain the question clearly enough to get you started.

Related

C# Can I use an enum as a for loop in place of int [duplicate]

This question already has answers here:
How to enumerate an enum?
(33 answers)
Closed 4 years ago.
So, I had this bright idea. I need to loop though all directions in a flathead hex. So, given the enum
public enum HexDirectionFlat
{
UP, UP_LEFT, DOWN_LEFT, DOWN, DOWN_RIGHT, UP_RIGHT
}
Is then this a valid for-loop?
for(HexDirectionFlat dir = HexDirectionFlat.UP; dir <= HexDirectionFlat.UP_RIGHT; dir++)
If so, are there any performence reasons not to use this?
Is then this a valid for-loop?
Yes, absolutely.
If so, are there any performance reasons not to use this?
No, this is a very efficient way of iterating over enum values - likely to be more efficient than calling Enum.GetValues which needs to allocate an array, for example.
The disadvantages are:
You need to know the "lowest" value of your enum (so adding a new lower value would involve changing every loop like this)
You need to know the "highest" value of your enum (so adding a new lower value would involve changing every loop like this)
If your enum has "gaps" (e.g. values 0, 1, 3, 4, 5 - but no 2) your loop won't skip over those gaps
If your enum goes right up to the highest value of the underlying type (e.g. 255 for a byte-based enum) the loop will never terminate
You could use constants to mitigate the first two points; the third point would only be relevant with explicitly-valued enums; the last point would be pretty rare. You could write unit tests to check for all of them.

Named numbers as variables [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I've seen this a couple of times recently in high profile code, where constant values are defined as variables, named after the value, then used only once. I wondered why it gets done?
E.g. Linux Source (resize.c)
unsigned five = 5;
unsigned seven = 7;
E.g. C#.NET Source (Quaternion.cs)
double zero = 0;
double one = 1;
Naming numbers is terrible practice, one day something will need to change, and you'll end up with unsigned five = 7.
If it has some meaning, give it a meaningful name. The 'magic number' five is no improvement over the magic number 5, it's worse because it might not actually equal 5.
This kind of thing generally arises from some cargo-cult style programming style guidelines where someone heard that "magic numbers are bad" and forbade their use without fully understanding why.
Well named variables
Giving proper names to variables can dramatically clarify code, such as
constant int MAXIMUM_PRESSURE_VALUE=2;
This gives two key advantages:
The value MAXIMUM_PRESSURE_VALUE may be used in many different places, if for whatever reason that value changes you need to change it in only one place.
Where used it immediately shows what the function is doing, for example the following code obviously checks if the pressure is dangerously high:
if (pressure>MAXIMUM_PRESSURE_VALUE){
//without me telling you you can guess there'll be some safety protection in here
}
Poorly named variables
However, everything has a counter argument and what you have shown looks very like a good idea taken so far that it makes no sense. Defining TWO as 2 doesn't add any value
constant int TWO=2;
The value TWO may be used in many different places, perhaps to double things, perhaps to access an index. If in the future you need to change the index you cannot just change to int TWO=3; because that would affect all the other (completely unrelated) ways you've used TWO, now you'd be tripling instead of doubling etc
Where used it gives you no more information than if you just used "2". Compare the following two pieces of code:
if (pressure>2){
//2 might be good, I have no idea what happens here
}
or
if (pressure>TWO){
//TWO means 2, 2 might be good, I still have no idea what happens here
}
Worse still (as seems to be the case here) TWO may not equal 2, if so this is a form of obfuscation where the intention is to make the code less clear: obviously it achieves that.
The usual reason for this is a coding standard which forbids magic numbers but doesn't count TWO as a magic number; which of course it is! 99% of the time you want to use a meaningful variable name but in that 1% of the time using TWO instead of 2 gains you nothing (Sorry, I mean ZERO).
this code is inspired by Java but is intended to be language agnostic
Short version:
A constant five that just holds the number five is pretty useless. Don't go around making these for no reason (sometimes you have to because of syntax or typing rules, though).
The named variables in Quaternion.cs aren't strictly necessary, but you can make the case for the code being significantly more readable with them than without.
The named variables in ext4/resize.c aren't constants at all. They're tersely-named counters. Their names obscure their function a bit, but this code actually does correctly follow the project's specialized coding standards.
What's going on with Quaternion.cs?
This one's pretty easy.
Right after this:
double zero = 0;
double one = 1;
The code does this:
return zero.GetHashCode() ^ one.GetHashCode();
Without the local variables, what does the alternative look like?
return 0.0.GetHashCode() ^ 1.0.GetHashCode(); // doubles, not ints!
What a mess! Readability is definitely on the side of creating the locals here. Moreover, I think explicitly naming the variables indicates "We've thought about this carefully" much more clearly than just writing a single confusing return statement would.
What's going on with resize.c?
In the case of ext4/resize.c, these numbers aren't actually constants at all. If you follow the code, you'll see that they're counters and their values actually change over multiple iterations of a while loop.
Note how they're initialized:
unsigned three = 1;
unsigned five = 5;
unsigned seven = 7;
Three equals one, huh? What's that about?
See, what actually happens is that update_backups passes these variables by reference to the function ext4_list_backups:
/*
* Iterate through the groups which hold BACKUP superblock/GDT copies in an
* ext4 filesystem. The counters should be initialized to 1, 5, and 7 before
* calling this for the first time. In a sparse filesystem it will be the
* sequence of powers of 3, 5, and 7: 1, 3, 5, 7, 9, 25, 27, 49, 81, ...
* For a non-sparse filesystem it will be every group: 1, 2, 3, 4, ...
*/
static unsigned ext4_list_backups(struct super_block *sb, unsigned *three,
unsigned *five, unsigned *seven)
They're counters that are preserved over the course of multiple calls. If you look at the function body, you'll see that it's juggling the counters to find the next power of 3, 5, or 7, creating the sequence you see in the comment: 1, 3, 5, 7, 9, 25, 27, &c.
Now, for the weirdest part: the variable three is initialized to 1 because 30 = 1. The power 0 is a special case, though, because it's the only time 3x = 5x = 7x. Try your hand at rewriting ext4_list_backups to work with all three counters initialized to 1 (30, 50, 70) and you'll see how much more cumbersome the code becomes. Sometimes it's easier to just tell the caller to do something funky (initialize the list to 1, 5, 7) in the comments.
So, is five = 5 good coding style?
Is "five" a good name for the thing that the variable five represents in resize.c? In my opinion, it's not a style you should emulate in just any random project you take on. The simple name five doesn't communicate much about the purpose of the variable. If you're working on a web application or rapidly prototyping a video chat client or something and decide to name a variable five, you're probably going to create headaches and annoyance for anyone else who needs to maintain and modify your code.
However, this is one example where generalities about programming don't paint the full picture. Take a look at the kernel's coding style document, particularly the chapter on naming.
GLOBAL variables (to be used only if you really need them) need to
have descriptive names, as do global functions. If you have a function
that counts the number of active users, you should call that
"count_active_users()" or similar, you should not call it "cntusr()".
...
LOCAL variable names should be short, and to the point. If you have
some random integer loop counter, it should probably be called "i".
Calling it "loop_counter" is non-productive, if there is no chance of it
being mis-understood. Similarly, "tmp" can be just about any type of
variable that is used to hold a temporary value.
If you are afraid to mix up your local variable names, you have another
problem, which is called the function-growth-hormone-imbalance syndrome.
See chapter 6 (Functions).
Part of this is C-style coding tradition. Part of it is purposeful social engineering. A lot of kernel code is sensitive stuff, and it's been revised and tested many times. Since Linux is a big open-source project, it's not really hurting for contributions — in most ways, the bigger challenge is checking those contributions for quality.
Calling that variable five instead of something like nextPowerOfFive is a way to discourage contributors from meddling in code they don't understand. It's an attempt to force you to really read the code you're modifying in detail, line by line, before you try to make any changes.
Did the kernel maintainers make the right decision? I can't say. But it's clearly a purposeful move.
My organisation have certain programming guidelines, one of which is the use of magic numbers...
eg:
if (input == 3) //3 what? Elephants?....3 really is the magic number here...
This would be changed to:
#define INPUT_1_VOLTAGE_THRESHOLD 3u
if (input == INPUT_1_VOLTAGE_THRESHOLD) //Not elephants :(
We also have a source file with -200,000 -> 200,000 #defined in the format:
#define MINUS_TWO_ZERO_ZERO_ZERO_ZERO_ZERO -200000
which can be used in place of magic numbers, for example when referencing a specific index of an array.
I imagine this has been done for "Readability".
The numbers 0, 1, ... are integers. Here, the 'named variables' give the integer a different type. It might be more reasonable to specify these constant (const unsigned five = 5;)
I've used something akin to that a couple times to write values to files:
const int32_t zero = 0 ;
fwrite( &zero, sizeof(zero), 1, myfile );
fwrite accepts a const pointer, but if some function needs a non const pointer, you'll end up using a non const variable.
P.S.: That always keeps me wondering what may be the sizeof zero .
How do you come to a conslusion that it is used only once? It is public, it could be used any number of times from any assembly.
public static readonly Quaternion Zero = new Quaternion();
public static readonly Quaternion One = new Quaternion(1.0f, 1.0f, 1.0f, 1.0f);
Same thing applies to .Net framework decimal class. which also exposes public constants like this.
public const decimal One = 1m;
public const decimal Zero = 0m;
Numbers are often given a name when these numbers have special meaning.
For example in the Quaternion case the identity quaternion and unit length quaternion have special meaning and are frequently used in a special context. Namely Quaternion with (0,0,0,1) is an identity quaternion so it's a common practice to define them instead of using magic numbers.
For example
// define as static
static Quaternion Identity = new Quaternion(0,0,0,1);
Quaternion Q1 = Quaternion.Identity;
//or
if ( Q1.Length == Unit ) // not considering floating point error
One of my first programming jobs was on a PDP 11 using Basic. The Basic interpreter allocated memory to every number required, so every time the program mentioned 0, a byte or two would be used to store the number 0. Of course back in those days memory was a lot more limited than today and so it was important to conserve.
Every program in that work place started with:
10 U0%=0
20 U1%=1
That is, for those who have forgotten their Basic:
Line number 10: create an integer variable called U0 and assign it the number 0
Line number 20: create an integer variable called U1 and assign it the number 1
These variables, by local convention, never held any other value, so they were effectively constants. They allowed 0 and 1 to be used throughout the program without wasting any memory.
Aaaaah, the good old days!
some times it's more readable to write:
double pi=3.14; //Constant or even not constant
...
CircleArea=pi*r*r;
instead of:
CircleArea=3.14*r*r;
and may be you would use pi more again (you are not sure but you think it's possible later or in other classes if they are public)
and then if you want to change pi=3.14 into pi=3.141596 it's easier.
and some other like e=2.71, Avogadro and etc.

C# - Suggestions of control statement needed

I'm a student and I got a homework i need some minor help with =)
Here is my task:
Write an application that prompts the user to enter the size of a square and display a square of asterisks with the sides equal with entered integer. Your application works for side’s size from 2 to 16. If the user enters a number less than 2 or greater then 16, your application should display a square of size 2 or 16, respectively, and an error message.
This is how far I've come:
start:
int x;
string input;
Console.Write("Enter a number between 2-16: ");
input = Console.ReadLine();
x = Int32.Parse(input);
Console.WriteLine("\n");
if (x <= 16 & x >= 2)
{
control statement
code
code
code
}
else
{
Console.WriteLine("You must enter a number between 2 and 16");
goto start;
}
I need help with...
... what control statment(if, for, while, do-while, case, boolean) to use inside the "if" control.
My ideas are like...
do I write a code that writes out the boxes for every type of number entered? That's a lot of code...
..there must be a code containing some "variable++" that could do the task for me, but then what control statement suits the task best?
But if I use a "variable++" how am I supposed to write the spaces in the output, because after all, it has to be a SQUARE?!?! =)
I'd love some suggestions on what type of statements to use, or maybe just a hint, of course not the whole solution as I am a student!
It's not the answer you're looking for, but I do have a few suggestions for clean code:
Your use of Int32.Parse is a potential exception that can crash the application. Look into Int32.TryParse (or just int.TryParse, which I personally think looks cleaner) instead. You'll pass it what it's parsing and an "out" parameter of the variable into which the value should be placed (in this case, x).
Try not to declare your variables until you actually use them. Getting into the habit of declaring them all up front (especially without instantiated values) can later lead to difficult to follow code. For my first suggestions, x will need to be declared ahead of time (look into default in C# for default instantiation... it's, well, by default, but it's good information to understand), but the string doesn't need to be.
Try to avoid using goto when programming :) For this code, it would be better to break out the code which handles the value and returns what needs to be drawn into a separate method and have the main method just sit around and wait for input. Watch for hard infinite loops, though.
It's never too early to write clean and maintainable code, even if it's just for a homework assignment that will never need to be maintained :)
You do not have to write code for every type of number entered. Instead, you have to use loops (for keyword).
Probably I must stop here and let you do the work, but I would just give a hint: you may want to do it with two loops, one embedded in another.
I have also noted some things I want to comment in your code:
Int32.Parse: do not use Int32, but int. It will not change the meaning of your code. I will not explain why you must use int instead: it is quite difficult to explain, and you would understand it later for sure.
Avoid using goto statement, except if you were told to use it in the current case by your teacher.
Console.WriteLine("\n");: avoid "\n". It is platform dependent (here, Linux/Unix; on Windows it's "\r\n", and on MacOS - "\n\r"). Use Environment.NewLine instead.
x <= 16 & x >= 2: why & and not ||?
You can write string input = Console.ReadLine(); instead of string input; followed by input = Console.ReadLine();.
Since it's homework, we can't give you the answer. But here are some hints (assuming solid *'s, not white space in-between):
You're going to want to iterate from 1 to N. See for (int...
There's a String constructor that will allow you to avoid the second loop. Look at all of the various constructors.
Your current error checking does not meet the specifications. Read the spec again.
You're going to throw an exception if somebody enters a non-parsable integer.
goto's went out of style before bell-bottoms. You actually don't need any outer control for the spec you were given, because it's "one shot and go". Normally, you would write a simple console app like this to look for a special value (e.g., -1) and exit when you see that value. In that case you would use while (!<end of input>) as the outer control flow.
If x is greater or equal to 16, why not assign 16 to it (since you'll eventually need to draw a square with a side of length 16) (and add an appropriate message)?
the control statement is:
for (int i = 0; i < x; i++)
{
for ( int j = 0; j < x; j++ )
{
Console.Write("*");
}
Console.WriteLine();
}
This should print a X by X square of asterisks!
I'ma teacher and I left the same task to my students a while ago, I hope you're not one of them! :)

What is the fast way of getting an index of an element in an array? [duplicate]

This question already has answers here:
How to find the index of an element in an array in Java?
(15 answers)
Closed 6 years ago.
I was asked this question in an interview. Although the interview was for dot net position, he asked me this question in context to java, because I had mentioned java also in my resume.
How to find the index of an element having value X in an array ?
I said iterating from the first element till last and checking whether the value is X would give the result. He asked about a method involving less number of iterations, I said using binary search but that is only possible for sorted array. I tried saying using IndexOf function in the Array class. But nothing from my side answered that question.
Is there any fast way of getting the index of an element having value X in an array ?
As long as there is no knowledge about the array (is it sorted? ascending or descending? etc etc), there is no way of finding an element without inspecting each one.
Also, that is exactly what indexOf does (when using lists).
How to find the index of an element having value X in an array ?
This would be fast:
int getXIndex(int x){
myArray[0] = x;
return 0;
}
A practical way of finding it faster is by parallel processing.
Just divide the array in N parts and assign every part to a thread that iterates through the elements of its part until value is found. N should preferably be the processor's number of cores.
If a binary search isn't possible (beacuse the array isn't sorted) and you don't have some kind of advanced search index, the only way I could think of that isn't O(n) is if the item's position in the array is a function of the item itself (like, if the array is [10, 20, 30, 40], the position of an element n is (n / 10) - 1).
Maybe he wants to test your knowledge about Java.
There is Utility Class called Arrays, this class contains various methods for manipulating arrays (such as sorting and searching)
http://download.oracle.com/javase/6/docs/api/java/util/Arrays.html
In 2 lines you can have a O(n * log n) result:
Arrays.sort(list); //O(n * log n)
Arrays.binarySearch(list, 88)); //O(log n)
Puneet - in .net its:
string[] testArray = {"fred", "bill"};
var indexOffset = Array.IndexOf(testArray, "fred");
[edit] - having read the question properly now, :) an alternative in linq would be:
string[] testArray = { "cat", "dog", "banana", "orange" };
int firstItem = testArray.Select((item, index) => new
{
ItemName = item,
Position = index
}).Where(i => i.ItemName == "banana")
.First()
.Position;
this of course would find the FIRST occurence of the string. subsequent duplicates would require additional logic. but then so would a looped approach.
jim
It's a question about data structures and algorithms (altough a very simple data structure). It goes beyond the language you are using.
If the array is ordered you can get O(log n) using binary search and a modified version of it for border cases (not using always (a+b)/2 as the pivot point, but it's a pretty sophisticated quirk).
If the array is not ordered then... good luck.
He can be asking you about what methods you have in order to find an item in Java. But anyway they're not faster. They can be olny simpler to use (than a for-each - compare - return).
There's another solution that's creating an auxiliary structure to do a faster search (like a hashmap) but, OF COURSE, it's more expensive to create it and use it once than to do a simple linear search.
Take a perfectly unsorted array, just a list of numbers in memory. All the machine can do is look at individual numbers in memory, and check if they are the right number. This is the "password cracker problem". There is no faster way than to search from the beginning until the correct value is hit.
Are you sure about the question? I have got a questions somewhat similar to your question.
Given a sorted array, there is one element "x" whose value is same as its index find the index of that element.
For example:
//0,1,2,3,4,5,6,7,8,9, 10
int a[10]={1,3,5,5,6,6,6,8,9,10,11};
at index 6 that value and index are same.
for this array a, answer should be 6.
This is not an answer, in case there was something missed in the original question this would clarify that.
If the only information you have is the fact that it's an unsorted array, with no reletionship between the index and value, and with no auxiliary data structures, then you have to potentially examine every element to see if it holds the information you want.
However, interviews are meant to separate the wheat from the chaff so it's important to realise that they want to see how you approach problems. Hence the idea is to ask questions to see if any more information is (or could be made) available, information that can make your search more efficient.
Questions like:
1/ Does the data change very often?
If not, then you can use an extra data structure.
For example, maintain a dirty flag which is initially true. When you want to find an item and it's true, build that extra structure (sorted array, tree, hash or whatever) which will greatly speed up searches, then set the dirty flag to false, then use that structure to find the item.
If you want to find an item and the dirty flag is false, just use the structure, no need to rebuild it.
Of course, any changes to the data should set the dirty flag to true so that the next search rebuilds the structure.
This will greatly speed up (through amortisation) queries for data that's read far more often than written.
In other words, the first search after a change will be relatively slow but subsequent searches can be much faster.
You'll probably want to wrap the array inside a class so that you can control the dirty flag correctly.
2/ Are we allowed to use a different data structure than a raw array?
This will be similar to the first point given above. If we modify the data structure from an array into an arbitrary class containing the array, you can still get all the advantages such as quick random access to each element.
But we gain the ability to update extra information within the data structure whenever the data changes.
So, rather than using a dirty flag and doing a large update on the next search, we can make small changes to the extra information whenever the array is changed.
This gets rid of the slow response of the first search after a change by amortising the cost across all changes (each change having a small cost).
3. How many items will typically be in the list?
This is actually more important than most people realise.
All talk of optimisation tends to be useless unless your data sets are relatively large and performance is actually important.
For example, if you have a 100-item array, it's quite acceptable to use even the brain-dead bubble sort since the difference in timings between that and the fastest sort you can find tend to be irrelevant (unless you need to do it thousands of times per second of course).
For this case, finding the first index for a given value, it's probably perfectly acceptable to do a sequential search as long as your array stays under a certain size.
The bottom line is that you're there to prove your worth, and the interviewer is (usually) there to guide you. Unless they're sadistic, they're quite happy for you to ask them questions to try an narrow down the scope of the problem.
Ask the questions (as you have for the possibility the data may be sorted. They should be impressed with your approach even if you can't come up with a solution.
In fact (and I've done this in the past), they may reject all your possibile approaches (no, it's not sorted, no, no other data structures are allowed, and so on) just to see how far you get.
And maybe, just maybe, like the Kobayashi Maru, it may not be about winning, it may be how you deal with failure :-)

Determining if enum value is in list (C#)

I am building a fun little app to determine if I should bike to work.
I would like to test to see if it is either Raining or Thunderstorm(ing).
public enum WeatherType : byte
{ Sunny = 0, Cloudy = 1, Thunderstorm = 2, Raining = 4, Snowing = 8, MostlyCloudy = 16 }
I was thinking I could do something like:
WeatherType _badWeatherTypes = WeatherType.Thunderstorm | WeatherType.Raining;
if(currentWeather.Type == _badWeatherTypes)
{
return false;//don't bike
}
but this doesn't work because _badWeatherTypes is a combination of both types. I would like to keep them separated out because this is supposed to be a learning experience and having it separate may be useful in other situations (IE, Invoice not paid reason's etc...).
I would also rather not do: (this would remove the ability to be configured for multiple people)
if(WeatherType.Thunderstorm)
{
return false; //don't bike
}
etc...
Your current code will say whether it's exactly "raining and thundery". To find out whether it's "raining and thundery and possibly something else" you need:
if ((currentWeather.Type & _badWeatherTypes) == _badWeatherTypes)
To find out whether it's "raining or thundery, and possibly something else" you need:
if ((currentWeather.Type & _badWeatherTypes) != 0)
EDIT (for completeness):
It would be good to use the FlagsAttribute, i.e. decorate the type with [Flags]. This is not necessary for the sake of this bitwise logic, but affects how ToString() behaves. The C# compiler ignores this attribute (at least at the moment; the C# 3.0 spec doesn't mention it) but it's generally a good idea for enums which are effectively flags, and it documents the intended use of the type. At the same time, the convention is that when you use flags, you pluralise the enum name - so you'd change it to WeatherTypes (because any actual value is effectively 0 or more weather types).
It would also be worth thinking about what "Sunny" really means. It's currently got a value of 0, which means it's the absence of everything else; you couldn't have it sunny and raining at the same time (which is physically possible, of course). Please don't write code to prohibit rainbows! ;) On the other hand, if in your real use case you genuinely want a value which means "the absence of all other values" then you're fine.
I'm not sure that it should be a flag - I think that you should have an range input for:
Temperature
How much it's raining
Wind strength
any other input you fancy (e.g. thunderstorm)
you can then use an algorithm to determine if the conditions are sufficiently good.
I think you should also have an input for how likely the weather is to remain the same for cycling home. The criteria may be different - you can shower and change more easliy when you get home.
If you really want to make it interesting, collect the input data from a weather service api, and evaulate the decision each day - Yes, I should have cycled, or no, it was a mistake. Then perhaps you can have the app learn to make better decisions.
Next step is to "socialize" your decision, and see whether other people hear you are making the same decisions.
use the FlagsAttribute. That will allow you to use the enum as a bit mask.
You need to use the [Flags] attribute (check here) on your enum; then you can use bitwise and to check for individual matches.
You should be using the Flags attribute on your enum. Beyond that, you also need to test to see if a particular flag is set by:
(currentWeather.Type & WeatherType.Thunderstorm == WeatherType.Thunderstorm)
This will test if currentWeather.Type has the WeatherType.Thunderstorm flag set.
I wouldn't limit yourself to the bit world. Enums and bitwise operators are, as you found out, not the same thing. If you want to solve this using bitwise operators, I'd stick to just them, i.e. don't bother with enums. However, I'd something like the following:
WeatherType[] badWeatherTypes = new WeatherType[]
{
WeatherType.Thunderstorm,
WeatherType.Raining
};
if (Array.IndexOf(badWeatherTypes, currentWeather.Type) >= 0)
{
return false;
}

Categories