I'm reviewing code review suggestions written from/to various developers and came across an interesting one.
Someone originally wrote a basic comparison in LINQ (EF to be specific):
myTable.Where(i => i.MyValue == 1);
Where 1 is an unchanging TypeId stored in the database.
The suggestion was to remove the hard coded value of 1 in favor of a const. So for example it would be rewritten as:
const int valueId = 1;
myTable.Where(i => i.MyValue == valueId);
From the suggestion point of view I get where they were coming from with the const since the code only ever needs a single copy of this value. But perhaps the compiler is smart enough to recognize that this is an unchanging value and treats it similarly.
So the question remains, does this kind of code refactor actually hold any weight other than eliminating "magic numbers"?
At this level, it is highly unlikely it matters what is produced at the compiler. It is likely the same anyway. The point is, what is safer for usage and easier to understand? Does '1' represent anything in particular except the literal value '1'? Based on the code snippet, I would guess that it does, and that is very good grounds for introducing a constant field because you now know exactly what is being checked against here.
Is this literal value '1' used in any other places that would need to be changed if the value change, for example, to '2'? If so, that also is very good grounds for introducing a constant field because now you only have to change the value in a single place, rather than search your entire code base, and most likely missing at least one instance.
Also, credit to Ixrec from Programmers, valueId is a terrible name for a constant as it does not say what the value is. A better name would be answersId, if, for example, the '1' represented answers while '0' represented questions and '2' represented comments.
First of all, both versions of the code will compile to exactly the same IL.
A constant is not a variable. Any usage of a constant is replaced at compile-time by it's value.
There are 2 advantages of using a const instead of a literal
The constant can be defined once and used in many places. So if you ever need to change the value of the constant, you only need to change it in one place*
You can give a meaningful name to the constant.
(*) Never change value of a public const field - all other assemblies using this constant will have to be recompiled to use the updated value.
Related
I've run into this pattern repeatedly in a project I'm working with:
int myIntValue = int.Parse(myNumericUpDown.Value.ToString());
This seems a little bit bananas to me, get a string from a decimal and then parse the string to get an int, and I wonder if there is something I'm missing that necessitates it. Seems like it has to be deliberate. Is there a reason that should be used rather than the obvious approach:
int myIntValue = (int)myNumericUpDown.Value;
Or:
int myIntValue = Convert.ToInt32(myNumericUpDown.Value);
Of course we cannot look into the mind of the programmer who wrote that code initially, but doing numeric conversions through strings is quite common with newer programmers. Presumably they first wrote
int myIntValue = myNumericUpDown.Value
got a compiler error, found Int32.Parse and put the pieces together.
There is really no reason at all to convert it to a string first, and then parse an integer from that - if anything it is inefficient and awkward to read.
In fact note that if for whatever reason the ToString gives an actual decimal number (like 3.0 instead of 3) the code will throw a System.FormatException which is not caught. From the assumption that you are not seeing that exception when running, I deduce that the control is set such that the Value property is always an integer, never something like 1.932, hence I would argue that the fastest way to get it as an integer is a hard cast
int myIntValue = (int)myNumericUpDown.Value;
(and add a try/catch for the inevitable case that your form designer messes up and sets the initial value of the control to 0.5).
I was reading the MSDN article of the boolean structure, when I saw that a boolean has two fields: TrueString and FalseString. These respectively return "True" and "False".
After some searching, the only example I could find is in this dotnetperls article. The article states:
Programs often need these strings. TrueString and FalseString are a useful pair of readonly members. They represent truth values in string format. They provide indirection and abstraction over directly using string literals.
So appearantly it's useful for some situations. But the same article fails to provide a realistic example (IMHO anyway).
Some further reading also brought this to my attention: TrueString and FalseString are public static readonly fields. And this dornetperls article states:
The language specification recommends using public static readonly fields ... when the field is subject to change in the future.
Now this I can somewhat understand. If the .NET developers ever decide to change "True" and "False" to respectively "OkeyDokey" and "Negatory", it's smart to use TrueString and or FalseString.
But that still leaves me with the question: in what kind of scenario do you want to compare a string with the string literal of a boolean? Because appearantly: "Programs often need" them.
For the same reason that string.Empty exists. Some people prefer a semantically named value in code over a literal one.
In modern .NET (anything after .NET Framework) the following code prints True three times:
Console.WriteLine(ReferenceEquals("True", bool.TrueString));
Console.WriteLine(ReferenceEquals("False", bool.FalseString));
Console.WriteLine(ReferenceEquals("", string.Empty));
This tells us there is zero runtime difference between the literals and the fields. They are exactly the same object at runtime.
Try this for yourself on sharplab.io here.
Others have mentioned using it to compare with when parsing boolean strings, but I would not recommend that. If you want to convert a string to a bool, use bool.TryParse or bool.Parse. Using == does a case-sensitive comparison, which is probably not what you want. Furthermore, the framework's methods are optimised specifically for common cases. You can see these optimisations in the code on GitHub here: https://github.com/dotnet/runtime/blob/f8fa9f6d1554e8db291187dd7b2847162703381e/src/libraries/System.Private.CoreLib/src/System/Boolean.cs#L226
If the program stores data in a human readable file or database, it may need to store values as strings. When you read the data back in, if you know the data was written by your application and uses a standard string representation, you can compare x == bool.TrueString faster than you can bool.TryParse(x ...). You could also validate the data by making sure all values x == bool.TrueString || x == bool.FalseString
If the data was typed by humans, or a different system, TryParse is a better option, as it accepts more values as true and differentiates between a definite false and an invalid input. (MSDN Boolean TryParse)
In easy words. Boolean is a Structure. this boolean expose ToString() method which represent a human readable text for the users. So if you write some thing like.
bool b = false;
b.ToString();
the output will be the "False" insteed of 0. the "False" is readable by human and easyly being captured.
Also some where you may want to parse a text value to a boolean value. so these also can be represented as boolean values. for example. we use
Boolean.TryParse("false" ,out mybool)
the false value is being set by the Tryparse method as this finds that we can read values from strings tool.
It can be used as a default value for missing "stringly-typed" configuration parameters. Here's a concrete example I've recently used:
if (bool.Parse(ConfigurationManager.AppSettings["IsTestMode"] ?? bool.FalseString)) ...
...which is - in my humble opinion - simpler and more readable than
var isTestModeString = ConfigurationManager.AppSettings["IsTestMode"];
if (isTestModeString != null && bool.Parse(isTestModeString)) ...
(I deliberately do not use TryParse here, since I do not want to silently ignore invalid values. I want an exception to be thrown, if the configuration value is present and something other than True or False.)
There are many situations where you may need to compare if a string is equal to "True", such as checking an API response. Note: it's more efficient to compare strings but often safer to parse.
The only advantage to using the built-in properties is you won't make typos (assuming you have Intellisense) and you don't have to remember the casing (e.g. "true" instead of "True).
What are some possible ways to name a variable representing a range of numbers? For example, I am working on a metrics application that displays the age of certain items in a person's queue. They are measured in
0-50 days
51-100 days
100+ days
I've thought about spelling the range out: zeroToFifty, range0-50. I've also considered naming them by "sections": first, second, third, but this doesn't prove to be very descriptive at all. What have you guys done to represent number ranges?
First, a name like ZeroToFifty isn't really very descriptive, hardly any better than if (number < 50). Variable names should provide more information if possible, while still being brief.
Second, I'd advise against embedding the numerical values into the constants - if you decide that the bottom range goes to 60 then a ZeroToFifty naming won't match any more. It will be much easier to adjust the values later if you don't have to refactor a name change throughout your codebase. Also, users of the constant probably don't care about 50, they care about "is it young or old?".
So you need to think "what do these number ranges represent"?
It depends on the usage, but you may find Young, Mature, Old works well for your case, as it describes the age of the item (and thus gives you strong clues about the meaning or usage of the value). Or maybe Modern, Classic, Vintage. Or Baby, Child, Adult. (If they "fit" the usage you have in mind).
In C# if you use an enumerated type, the typename must always be used, and that also can help clarify the meaning: ItemAge.Young/Mature/Old or TimeInQueue.Short/Medium/Long.
What I want to do is be told the type, value (if there is one at compile-time) and other information (I do not know what I need now) of a selection of an expression.
For example, if I have an expression like
int i = unchecked((short)0xFF);
selecting 0xFF will give me (Int32, 255), while selecting ((short)0xFF) will give me (Int16, 255), and selecting i will give me (Int32, 255).
Reason why I want such a feature is to be able to verify my assumptions. It's pretty easy to assume that 0xFF is a byte but it is actually an int. I could of course refer to the C# Language Specifications all the time, but I think it's inefficient to have to refer to it everytime I want to check something out. I could also use something like ANTLR but the learning curve is high.
I do intend to read the entire specs and learn ANTLR and about compilers, but that's for later. Right now I wish to have tools to help me get the job done quickly and accurately.
Another case in point:
int? i = 0x10;
int? j = null;
int x;
x = (i >> 4) ?? -1;//x=1
x = (j >> 4) ?? -1;//x=-1
It may seem easy to you or even natural for the bottom two lines in the code above. (Maybe one should avoid code like these, but that's another story) However, what msdn says about the null-coalescing operator is lacking information to tell me that the above code ((i>>4)??) is legal (yet it is, and it is). I had to dig into grammar in the specs to know what's happening:
null-coalescing-expression
conditional-or-expression
conditional-and-expression
exclusive-or-expression
and-expression
equality-expression
relational-expression
shift-expression
shift-expression right-shift additive-expression
... (and more)
Only after reading so much can I get a satisfactory confirmation that it is valid code and does what I think it does. There should be a much simpler way for the average programmer to verify (not about validity, but whether it behaves as thought or not, and also to satisfy my curiosity) such code without having to dive into that canonical manual. It doesn't necessary have to be a VS plugin. Any alternative that is intuitive to use will do just as well.
Well, I'm not aware of any add-ins that do what you describe - however, there is a trick you can use figure out the type of an expression (but not the compile-time value):
Assign the expression to a var variable, and hover your mouse over the keyword var.
So for example, when you write:
var i = unchecked((short)0xFF);
and then hover your mouse over the keyword var, you get a tooltip that says something like:
Struct System.Int16
Represents a 16-bit signed integer.
This is definitely a bit awkward - since you have to potentially change code to make it work. But in a pinch, it let's you get the compiler to figure out the type of an expression for you.
Keep in mind, this approach doesn't really help you once you start throwing casts into the picture. For instance:
object a = 0xFF;
var z = (string)a; // compiles but fails at runtime!
In the example above, the IDE will dutifully report that the type of var z is System.String - but this is, of course, entirely wrong.
Your question is a little vague on what you are looking for, so I don't know if "improved" intellisense solves it, but I would try the Productivity Power Tools.
I'm constantly running up against this when writing queries with LINQ-to-XML: the Value property of an XElement is a string, but the data may actually be an integer, boolean, etc.
Let's say I have a "where" clause in my query that checks if an ID stored in an XElement matches a local (integer) variable called "id". There are two ways I could do this.
1. Convert "id" to string
string idString = id.ToString();
IEnumerable<XElement> elements =
from
b in TableDictionary["bicycles"].Elements()
where
b.Element(_ns + "id").Value == idString
select
b;
2. Convert element value to int
IEnumerable<XElement> elements =
from
b in TableDictionary["bicycles"].Elements()
where
int.Parse(b.Element(_ns + "id").Value) == id
select
b;
I like option 2 because it does the comparison on the correct type. Technically, I could see a scenario where converting a decimal or double to a string would cause me to compare "1.0" to "1" (which would be unequal) versus Decimal(1.0) to Decimal(1) (which would be equal). Although a where clause involving decimals is probably pretty rare, I could see an OrderBy on a decimal column--in that case, this would be a very real issue.
A potential downside of this strategy, however, is that parsing tons of strings in a query could result in a performance hit (although I have no idea if it would be significant for a typical query). It might be more efficient to only parse element values when there is a risk that a string comparison would result in a different result than a comparison of the correct value type.
So, do you parse your element values religiously or only when necessary? Why?
Thanks!
EDIT:
I discovered a much less cumbersome syntax for doing the conversion.
3. Cast element to int
IEnumerable<XElement> elements =
from
b in TableDictionary["bicycles"].Elements()
where
(int)b.Element(_ns + "id") == id
select
b;
I think this will be my preferred method from now on...unless someone talks me out of it :)
EDIT II:
It occurred to me since posting my question that: THIS IS XML. If I really had enough data for performance to be an issue, I would probably be using a real database. So, yet another reason to go with casting.
Its difficult to assess the performance issues here without measuring. But I think you have two scenarios.
If you need to use most (or all) of the values in an expression sooner or later, then it is probably best to pay the CPU costs of converting to native types up front - discarding the XML string data early.
If you are only going to touch (evaluate or use) a few of the values, then it will most likely be cheaper in terms of CPU time to convert string data to native types lazily - at the time of (or close to it temporally) consumption.
Now, this is just the CPU time considerations. I suggest that it is likely that the data itself will take up considerably less memory once converted to native value types. This lets you discard the string (XML) data early.
In short, it is rare for questions like this to have black or white answers: it will depend on your scenario, the complexity of the data, how much data there is, and when it will be used (touched or evaluated).
Update
In Dan's comment to my original answer, he ask for a general rule of thumb in cases where there is not time, or reason to do detailed measurements.
My suggestion is to prefer conversion to native types at XML parsing time, not keep the string data around and parse lazily. Here is my reasoning
The code will already be burning some CPU, I/O, and memory resources at parasing time.
The code is like to be simpler doing the conversions at load time (rather than at another time) as this can all be coded in a simple procedural way.
This is likely to be more memory efficient as well.
When the data needs to be used, it is already in a native format - this will be much better performing than dealing with string data at consumption time: comparisons and computation with native types will usually be much more efficient than dealing with data in string format. This is likely to keep the consuming code simpler as well.
Again, I'm suggesting this as a rule of thumb :) There will be scenarios where another approach is more optimal from a performance standpoint, or will make the code 'better' in some way (more cohesive, modular, easier to maintain, etc).
This is one of those cases where you will most likely need to measure the results to be sure you are doing the right thing.
I agree with your second edit. If performance is an issue, you will gain much more by using a more queryable data structure (or just cache a dictionary by ID from your XML for repeated lookups) than by changing how you compare/parse values.
That said, my preference would be using the various explicit cast overrides on XElement. Also, if your ID could ever be empty (better safe than sorry), you can also do an efficient cast to int?.