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;
}
Related
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.
A standard enumeration in System.Windows.Forms:
[Flags]
public enum DragDropEffects
{
Scroll = -2147483648,
//
// Summary:
// The combination of the System.Windows.DragDropEffects.Copy, System.Windows.Forms.DragDropEffects.Link,
// System.Windows.Forms.DragDropEffects.Move, and System.Windows.Forms.DragDropEffects.Scroll
// effects.
All = -2147483645,
None = 0,
Copy = 1,
Move = 2,
Link = 4,
}
Quite a strange value for Scroll, don't you think?
As I understand these values all come from "the old times" of COM\OLE DROPEFFECT... But why were they chosen so in the first place? Did author try to reserve the interval between 8 and 0x80000000 for something? Is it usefule somehow or is there an interesting story behind it or it's just another long-lived illustration of the YAGNI principle?
It is a status flag, separate from the principal drop effects (Copy/Move/Link). Short from leaving room for future drop effects, picking the high bit allows a trick like checking if the value is negative. Same kind of idea as an HRESULT or the GetAsyncKeyState return value.
Yes, it looks like an "interesting" hack of some sort. Common sense would suggest using 8, but maybe there's some Windows version related reason why 8 couldn't be used, and so the author used -2147483645 (-0x80000000) instead. It's not that unusual a number - whoever wrote it is just starting with a binary '1' from the high significant end rather than the low significant end.
Perhaps scrolling was regarded in some other group of drag/drop effects to copy/move/link, and so the author wanted to place it at the other end of the word, along with any other future similarly different effects.
Maybe there's some awful piece of logic somewhere to test to see if a DragDropEffects variable is greater than zero (intending to mean "anything that isn't none"), and Scroll should not fall in that range?
Bit of a mystery. At the very least you'd think they would put the constant in as hex, to show it's not just some totally random number.
This allows a quick check for > 0 in order to know whether Copy, Move, or Link are being invoked. It excludes None as well as Scroll.
I have an algorithm that returns a list of classifications(strings) dependant on the two arguments given to the algorithm: a type variable, and an extra category string that allows certain special classifications to be added to the result list.
The current implementation, is unreadable and unscalable due to the expression of the rules as ifs, and switch statements. Also the rules are hard coded.
A simplified version of the code:
private static List<string> DetermineTypes(Type x, object category) {
List<string> Types = new List<string>();
if (category is DateTime) {
types.Add("1");
types.Add("2");
types.Add("3");
} else if (category is string) {
switch ((string)category) {
case "A":
Types.Add("4");
break;
case "B":
case "C":
case "D":
Types.Add("5");
break;
case "":
Types = DetermineTypesFromX(Types, x);
break;
default:
Types.Add("6");
break;
}
}
return graphTypes;
}
private static List<string> DetermineTypesFromX(List<string> Types, Type x) {
if (x.Equals(typeof(int))) {
Types.Add("7");
} else if (x.Equals(typeof(double))) {
Types.Add("8");
} else if (x.Equals(typeof(System.DateTime))) {
Types.Add("9");
Types.Add("10");
}
return Types;
}
I was thinking that it would be good to maybe specify these with xml, so that a code change wasn't needed for new types/rules, but that is most probably too heavyweight for the situation. Basically I am trying to solve the problem that a new 'Type' may be added at anytime: common case would be that it is one of the 'rules' above, and an unlikely edge case that a new 'rule' branch may have to be added.
I am still to determine whether the work needed it to make it fully dynamic using xml defined rules( or any other way) is worth it compared to the likelihood of the edge cases ever happening and the business environment(schedules etc).
But my main point of the question is how could you elegantly simplify the nested conditional code above? maybe incorporating more flexibility into the design for increased scalability?
I was wondering if using a combination of F# pattern matching might be an appropriate solution? (NB: Never used F# before, have been curious as of late, so thats why I am asking)
A pattern known as dispatch tables has been recently discussed in the following two blog posts and will probably be of interest to you:
Aaron Feng
K. Scott Allen
I wouldn't shy away from a config-based option; it usually has the advantage of not requiring a rebuild. If you don't want that, another option might be type-metadata via an attribute. This would make it trivial to add data for new types (that you write), and you can (indirectly) add attributes to exiting types (int etc) via TypeDescriptor.AddAttributes - as long as you use TypeDescriptor.GetAttributes to get them back out again ;-p
Whether this is a good idea or not... well, reflection (and the twin, TypeDescriptor) can be slow, so if you want to use this in a tight loop I'd look first at something involving a dictionary.
Your problem may be coded in terms of decision tree or decision table
Also, there is posts into Chris Smith's blog about decision trees:
Awesome F# - Decision Trees – Part I and
Awesome F# - Decision Trees – Part II
I would suggest you look at a business rules/inference engine. NxBRE has a good community around it and is quite mature. This may be beyond your immediate requirements but if you expect these rules to increase in complexity over time a BRE will provide a nice framework to keep things under control.
Since you mention F#, here is some F# code with very similar behavior to the C# code:
open System
let DetermineTypesFromX(x:Type) =
if x.Equals(typeof<int>) then
["7"]
elif x.Equals(typeof<double>) then
["8"]
elif x.Equals(typeof<DateTime>) then
["9"; "10"]
else
[]
let DetermineTypes(x:Type, category:obj) =
match category with
| :? DateTime -> ["1"; "2"; "3"]
| :? string as s ->
match s with
| "A" -> ["4"]
| "B" | "C" | "D" -> ["5"]
| "" -> DetermineTypesFromX(x)
| _ -> ["6"]
| _ -> []
That said, I would recommend considering a table-driven approach as an alternative to hard-coded if/switch logic, regardless of whether you move the logic out of the code and into a config file.
I came across similar situation and I've asked a few questions previously in regards to the similar problem that may help you.
The system I did was a configuration driven, rule based dynamic system. All configurations and rules were saved in database. Decision tables were constructed dynamically based on the values and rules retrived from database. Values were then converted and compared in C#. Here's the question I asked about dynamic decision table in C#. And the question regarding dyanmically convert and compare values retrived from databse.
So I end up having something simliar to this in terms of the config table (just an example):
Conditions IsDecision LHS Operator RHS
TTFF False PostCode > 100
TFTF False PostCode < 10000
FTTT True
Note: LHS is the property name of the object.
The above table in plain English:
Condition 1 PostCode > 100 Yes Yes No No
Condition 2 PostCode < 10000 Yes No Yes No
Outcome 1 Yes
Outcome 2 Yes
Outcome 3 Yes
Outcome 4 Yes
Then you have other tables/configs to determine the action for each outcome.
The core parts of the implementation are how to dynamically construct decision table and how to dynamic convert and compare string values, all of which I have provided links to the specific implementations in the above paragraph. I believe you can apply similar concepts in your situations and I hope I've explained the concept in general.
Other Resources:
Martin Fowler's decision tree article.
Luke's post on decision tree.
I'm interested in both style and performance considerations. My choice is to do either of the following ( sorry for the poor formatting but the interface for this site is not WYSIWYG ):
One:
string value = "ALPHA";
switch ( value.ToUpper() )
{
case "ALPHA":
// do somthing
break;
case "BETA":
// do something else
break;
default:
break;
}
Two:
public enum GreekLetters
{
UNKNOWN= 0,
ALPHA= 1,
BETA = 2,
etc...
}
string value = "Alpha";
GreekLetters letter = (GreekLetters)Enum.Parse( typeof( GreekLetters ), value.ToUpper() );
switch( letter )
{
case GreekLetters.ALPHA:
// do something
break;
case GreekLetters.BETA:
// do something else
break;
default:
break;
}
Personally, I prefer option TWO below, but I don't have any real reason other than basic style reasons. However, I'm not even sure there really is a style reason. Thanks for your input.
The second option is marginally faster, as the first option may require a full string comparison. The difference will be too small to measure in most circumstances, though.
The real advantage of the second option is that you've made it explicit that the valid values for value fall into a narrow range. In fact, it will throw an exception at Enum.Parse if the string value isn't in the expected range, which is often exactly what you want.
Option #1 is faster because if you look at the code for Enum.Parse, you'll see that it goes through each item one by one, looking for a match. In addition, there is less code to maintain and keep consistent.
One word of caution is that you shouldn't use ToUpper, but rather ToUpperInvariant() because of Turkey Test issues.
If you insist on Option #2, at least use the overload that allows you to specify to ignore case. This will be faster than converting to uppercase yourself. In addition, be advised that the Framework Design Guidelines encourage that all enum values be PascalCase instead of SCREAMING_CAPS.
I can't comment on the performance part of the question but as for style I prefer option #2. Whenever I have a known set of values and the set is reasonably small (less than a couple of dozen or so) I prefer to use an enum. I find an enum is a lot easier to work with than a collection of string values and anyone looking at the code can quickly see what the set of allowed values is.
This actually depends on the number of items in the enum, and you would have to test it for each specific scenario - not that it is likely to make a big difference. But it is a great question.
With very few values, the Enum.Parse is going to take more time than anything else in either example, so the second should be slower.
With enough values, the switch statement will be implemented as a hashtable, which should work the same speed with strings and enums, so again, Enum.Parse will probably make the second solution slower, but not by relatively as much.
Somewhere in the middle, I would expect the cost of comparing strings being higher than comparing enums would make the first solution faster.
I wouldn't even be surprised if it were different on different compiler versions or different options.
I would definitely say #1. Enum.Parse() causes reflection which is relatively expensive. Plus, Enum.Parse() will throw an Exception if its not defined and since there's no TryParse() you'd need to wrap it in Try/Catch block
Not sure if there is a performance difference when switching on a string value versus an enum.
One thing to consider is would you need the values used for the case statements elsewhere in your code. If so, then using an enum would make more sense as you have a singular definition of the values. Const strings could also be used.
I'm playing with the SubSonic RESTHandler for the first time and it's awesome... There is one quirk tho, that I'm curious about.
RESTHandler.cs (line 319):
//if this column is a string, by default do a fuzzy search
if(comp == Comparison.Like || column.IsString)
{
comp = Comparison.Like;
paramValue = String.Concat("%", paramValue, "%");
}
This little blurp of code forces all searches on string columns to wildcard searches by default. This seems counter intutive, since you've provided a nice set of comparisons we can add to a parameter (_is, _notequal, etc...). Is there a reason this was done? The EvalComparison uses "Comparison.Equals" as it's default, so unless a like is explicitly needed the " || column.IsString" looks like it should be removed since it breaks the ability to use different types of comparisons.
This was driving me crazy, since you can't do a "WHERE Field = X" without modifiying code...
Just curious if this is more of a feature than a bug...
Thanks!
Zach
It's because this is a LIKE operation which for a DB usually allows string operations. The feeling at the time was that if you wanted equals you could just use that.
It's been a while since I've touched this code - if you'd be kind enough to open a bug I'll take a look at it.
It does indeed look like a feature. It's based on the idea that, if I am searching for a string in a column without the wildcards, I must match the string exactly or I get no hits. I suspect that this was done to make programming search textboxes easier.