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).
Related
I got a small method that splits a string into two parts, retrieves one part and uses it to establish a connection to a server:
private void RetrieveData(string vesselCode)
{
string[] splitSelectedVessel = vesselCode.Split('_');
int selectedVessel = int.Parse(splitSelectedVessel[1]);
// URL of server to retrieve data.
// constructed with vesselCode.
string baseUrl = ".../vehicle/";
string jsonUrl = baseUrl + selectedVessel;
PtVehicle currentVessel = DownloadAndDeserialize<PtVehicle>(jsonUrl);
}
VesselCode containts two parts, combined with an '_' in between:
company code
vesselnumber
Both are of entry fields from a Xamarin project and are originally stored as strings.
Whenever the VesselNumber part gets too large, it just stops right after int selectedVessel = int.Parse(splitSelectedVessel[1]);. It seems to break out of the method above, without giving a warning or anything. I've tested it with breakpoints on every line. It simply stops running that method and goes on with whatever it was doing, often letting the app crash later on (since it needs that value). What is happening here?
I suppose that your number is all too long for an int. I don't know what can the maximum number be, but you can try long instead. Probably it's enough.
If it isn't then you have to do something with handling of too large numbers. You can write
if (long.TryParse(myString, out myValue)
{
// Your logic here
}
else
{
// Do something if the value is too large
}
I ended up fixing the issue with #Ilya Chernomordik's and the documentation provided by #Mihai.
The issue was that int selectedVessel = int.Parse(splitSelectedVessel[1]); parses the value of that string to an int. When the value was larger than the int max size, it crashed. Since VesselNumber is an ID and I don't have to calculate it, I simply solved it by storing it as a string:
string selectedVessel = splitSelectedVessel[1];
Another way is to store it as a long (int) of 64 bits, but this only "moves" the issue to a much larger number.
What is happening here is that you are throwing an exception. Consider the following code...
try
{
string s1 = "2147483649";
int j = int.Parse(s1);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
2147483649 is int.MaxValue + 1
This code generates the following message:
Value was either too large or too small for an Int32.
It should throw an System.OverflowException if the number is too big to be parsed as int.
According to Microsoft documentation long/ ulong has the biggest range.
You might have breaking for exceptions disabled if you are using Visual Studio so you might want to enable them to see what's the actual problem Debug->Windows->Exception Settings and make sure Common Language Runtime Exceptions are checked.
On the other hand, the best practice is to use the .TryParse approach when converting to an integral type.
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.
I have an XML file that contains a "script" of items to check and validate. What it does is reads in a value to check, and if that check is true, it does something. I originally wrote this to work with just integers, but I realize I need to make it work with more data types.
A sample check is like this...It sees if SomeValue is greater than 20.
<If field="SomeValue" test="#gt" value="20" />
*The field is just some string value. So for a double, the field would be something like 55.7.
All I do is do a int.TryParse on the value to see if I can cast the string (SomeValue) to an integer. If I can, I check to see if it is greater than 20. If not, I just assume false on the check.
Does anyone have any suggestions on how I could this with any data type? (i.e. string, double, DateTime)
Would Generics work? I have never used them so I dont know if they would be the best solution. Thanks.
The tricky bit is a parse when you don't know the types, but this can be done with TypeDescriptor.GetConverter:
object knownVal = 21; //perhaps obtained from reflection
Type type = typeof(int);
string text = "20";
object val = TypeDescriptor.GetConverter(type)
.ConvertFromInvariantString(text);
int rel = Comparer.Default.Compare(knownVal, val);
Generics is an option (especially with Comparer<T>.Default.Compare), but generics doesn't mix well with Type values only known at runtime. It can be done (MakeGenericType/MakeGenericMethod), but it is ugly and a bit slow.
To be honest, though: if it was me I would assume there is a small number of types that need handling here, and special-case them.
Hey, I am working on a school project and a line of code I just wrote kind of made me laugh and think to myself, "There must be a better way to do what I just did". So, my question is, is this really the best way to do this? It seems kind of silly. BTW, size is an int that is passed to this function.
int tiles = Convert.ToInt32(Math.Sqrt(Convert.ToDouble(size)));
I know this works, but is there a better way?
Since int is implicitly convertable to double, you can leave out the inner conversion:
int tiles = Convert.ToInt32(Math.Sqrt(size));
That being said, Convert.ToInt32 is overkill in this situation. You can also just use a simple cast, since you know it's going from double to int:
int tiles = (int)Math.Sqrt(size);
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.