Int32.Parse() VS Convert.ToInt32()? - c#

intID1 = Int32.Parse(myValue.ToString());
intID2 = Convert.ToInt32(myValue);
Which one is better and why?

They are exactly the same, except that Convert.ToInt32(null) returns 0.
Convert.ToInt32 is defined as follows:
public static int ToInt32(String value) {
if (value == null)
return 0;
return Int32.Parse(value, CultureInfo.CurrentCulture);
}

Well, Reflector says...
public static int ToInt32(string value)
{
if (value == null)
{
return 0;
}
return int.Parse(value, CultureInfo.CurrentCulture);
}
public static int Parse(string s)
{
return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
}
So they're basically the same except that Convert.ToInt32() does an added null check.

It depends on what you mean by "better" because "better" is subjective.
For instance - code readability. Some people prefer to see "Convert" in their code; others prefer to see "Parse".
In terms of speed, they're also both roughly equal according to these benchmarks.
Or do you always wants a value returned? As others have mentioned, ConvertTo returns a 0 (zero) for null values whereas you don't get that option with Parse.

Related

TryParsing from an object list to int | c#

I'm trying to take objects out of an object list to an int list. If the object list's value contains a string than I want to convert it to an int. the error that I'm getting is "cannot convert from 'object' to 'System.ReadOnlySpan'. I've tried looking up examples and information about lists made of objects but couldn't find anything.
I'm also at a loss as to what to do with the 'else' part of the code.
public class ListFilterer
{
public static IEnumerable(int) GetIntegersFromList(List(object) listOfItems)
{
List<int> Integers = new List<int>();
foreach (var value in listOfItems)
{
int number = 0;
bool success = Int32.TryParse(value, out number);
if (success)
{
Integers.Add(number);
}
else
{
Integers.Add(number);
}
}
return Integers;
}
}
It'll probably work out if you TryParse value.ToString() instead, if you're looking for anything that might look like an int and can be converted to an int. If you only want things that actually are ints, something like if(value is int number) should work if your c# version is recent. If it's older you may have to if(value is int) and then cast the value inside the if
Your code can be simplified to:
foreach(...){
int.TryParse(value.ToString(), out var n);
integers.Add(n);
}
Or
foreach(...){
if(value is int)
integers.Add((int)value);
else
integers.Add(0);
}
You could simply use:
var ints = listOfItems
.Select(o => { int.TryParse(o.ToString(), out int num); return num;} )
.ToList();
This will work as you wish, as if conversion fails num is 0 by default.
If Try Parse fails number is automatically 0 so you can directly write this
Int32.TryParse(value, out int number)
Integers.Add(number);
Maybe you can find the better way
var intList = objs.ConvertAll(delegate (object obj) { return (int)obj; });

C# converting a decimal to an int safely

I am trying to convert a decimal to an integer safely.
Something like
public static bool Decimal.TryConvertToInt32(decimal val, out int val)
this will return false if it cannot convert to an integer, and true w/ successful output if it can.
This is to avoid catching the OverflowException in decimal.ToInt32 method. What is the easiest way to do this?
Here:
public static bool TryConvertToInt32(decimal val, out int intval)
{
if (val > int.MaxValue || val < int.MinValue)
{
intval = 0; // assignment required for out parameter
return false;
}
intval = Decimal.ToInt32(val);
return true;
}
I would write an extension method for class decimal like this:
public static class Extensions
{
public static bool TryConvertToInt32(this decimal decimalValue, out int intValue)
{
intValue = 0;
if ((decimalValue >= int.MinValue) && (decimalValue <= int.MaxValue))
{
intValue = Convert.ToInt32(decimalValue);
return true;
}
return false;
}
}
You can use it in that way:
if (decimalNumber.TryConvertToInt32(out intValue))
{
Debug.WriteLine(intValue.ToString());
}
Compare the decimal against int.MinValue and int.MaxValue prior to the conversion.
What's wrong with using Int32.TryParse(string) ?
Why are you trying to avoid catching the OverflowException? It is there for a reason and you should totally catch it where you call Decimal.ToInt32(). Exceptions are used widely throughout the framework and users should catch them. The Try methods can help you around them to make code tighter and cleaner, but where the framework doesn't have a suitable method (Decimal.TryConvertToInt32() in this case) catching OverflowException is the appropriate thing to do. It is actually more clear than making an extension class or writing your own separate static method (both of those involve writing your own code where the framework is already giving you this functionality).

What's the correct way to not update an out variable

I've implemented a TryParse function for a class MinMax like this:
public static bool TryParse(string s, out MinMax result)
{
var parts = s.Split(' ');
if (parts.Length != 2)
{
return false;
}
float min;
float max;
if (!float.TryParse(parts[0].Trim(), out min) || !float.TryParse(parts[1].Trim(), out max))
{
return false;
}
result = new MinMax(min, max);
return true;
}
However this doesn't compile since apparently the out parameter needs to be written. What's the correct way to fix this? I would like to be able to use the function so that if the parsing fails, the parameter passed into it remains unchanged. I guess one way would be to add something like:
result = result;
but this line issues a warning.
Pass by ref:
public static bool TryParse(string s, ref MinMax result)
which means you will have to ensure the result parameter is initialised.
Update: It is better to stick to the well known semantics of TryParse. (I'm sometimes critised for answering the real question not the one that was asked! On this occasion it was the opposite!)
Assuming MinMax is a reference type, just assign null to it. Just like any other TryParse method would work.
Check out this code:
string s = "12dfsq3";
int i = 444;
int.TryParse(s, out i);
Console.WriteLine(i);
i will be set to 0 instead of remaining at 444.
Given that an out parameter doesn't even need to be initialized by the caller, you really have to do something with it.
You could use a ref parameter instead, those don't require you to touch them in your function.
I don't like these answers telling you to use a ref parameter as it changes the semantics of the method and will require callers to pass an initialised value.
Set result to the default value for MinMax, which is null if it's a reference type, or use the default operator.
result = default(MinMax);
The only correct way to not update an out variable is to throw an exception. Change out to ref.
You have to set the value of the out variable. You could use ref as other answers have suggested, but I wouldn't recommend it - that's not how the standard TryParse pattern is supposed to work. Besides, it's ugly and unnecessary.
It doesn't really matter what result contains in the failure case, since the bool that you return indicates whether the parsing was successful or not. Just return new MinMax(0, 0) or, if you prefer, default(MinMax):
public static bool TryParse(string s, out MinMax result)
{
string[] parts = s.Split(' ');
if (parts.Length == 2)
{
float min, max;
if (float.TryParse(parts[0].Trim(), out min)
&& float.TryParse(parts[1].Trim(), out max))
{
result = new MinMax(min, max);
return true;
}
}
result = default(MinMax); // or just use "result = new MinMax(0, 0);"
return false;
}

Check that integer type belongs to enum member

I want to check that some integer type belongs to (an) enumeration member.
For Example,
public enum Enum1
{
member1 = 4,
member2 = 5,
member3 = 9,
member4 = 0
}
Enum1 e1 = (Enum1)4 gives me member1
Enum1 e2 = (Enum1)10 gives me nothing and I want to check it.
Use Enum.IsDefined
Enum.IsDefined(typeof(Enum1), 4) == true
but
Enum.IsDefined(typeof(Enum1), 1) == false
As Sam says, you can use IsDefined. This is somewhat awkward though. You may want to look at my Unconstrained Melody library which would let you us:
Enum1 e2 = (Enum1)10;
if (e2.IsNamedValue()) // Will return false
{
}
It's probably not worth it for a single enum call, but if you're doing a lot of stuff with enums you may find some useful things in there.
It should be quicker than Enum.IsDefined btw. It only does a linear scan at the moment, but let me know if you need that to be improved :) (Most enums are small enough that they probably wouldn't benefit from a HashSet, but we could do a binary search...)
int testNum = 5;
bool isMember = Enum.GetValues(typeof(Enum1)).Cast<int>().Any(x => x == testNum);
You look through the values of the enum and compare them to the integer.
static bool EnumTest(int testVal, Enum e)
{
bool result = false;
foreach (var val in Enum.GetValues(typeof(Enum1)))
{
if ((int)val == testVal)
{
result = true;
break;
}
}
return result;
}
Edit: Looks like Sam has a better solution.
You can use Enum.GetValues to get all defined values. Then check if your value exists in that list.
http://msdn.microsoft.com/en-us/library/system.enum.getvalues.aspx
Be careful this won't work if you have an enum for 3 (Apples and Pears) the methods above won't detect it as valid.
[Flags]
public enum Fruit
{
Apples=1,
Pears=2,
Oranges =4,
}
Here's a succinct little snippet from an extension method I wrote a few years ago. Combines TryParse with IsDefined to do it all in one swoop and handle values that don't exist in the enum.
if (value != null)
{
TEnum result;
if (Enum.TryParse(value.ToString(), true, out result))
{
// since an out-of-range int can be cast to TEnum, double-check that result is valid
if (Enum.IsDefined(typeof(TEnum), result.ToString() ?? string.Empty))
{
return result;
}
}
}
Here's the extension for integer values
public static TEnum ParseToEnum<TEnum>(this int value, TEnum? defaultValue = null, bool useEnumDefault = false) where TEnum : struct
{
return ParseToEnumInternal(value, defaultValue, useEnumDefault);
}
And a usage
public enum Test
{
Value1 = 1,
Value2 = 3
}
var intValue = 1;
var enumParsed = intValue.ParseToEnum<Test>(); // converts to Test.Value1
intValue = 2;
enumParsed = intValue.ParseToEnum<Test>(); // either throws or converts to supplied default
enumParsed = 3.ParseToEnum<Test>(); // converts to Test.Value2
Some people don't like how it dangles off the end of the (potentially nullable) value, but I have an extension that handles null values of nullable types (int?) and I like it myself, so ...
I can post like a Gist of the whole extension method with all the overloads if you're interested.
Use:
if (Enum.IsDefined(typeof(Fruit),e2))
{
//Valid Value
}
else
{
//Invalid ENum Value
}
Found this useful. https://stackoverflow.com/a/64374930/16803533
no need to use IsDefined and No range checking

Lack of IsNumeric function in C#

One thing that has bothered me about C# since its release was the lack of a generic IsNumeric function. I know it is difficult to generate a one-stop solution to detrmine if a value is numeric.
I have used the following solution in the past, but it is not the best practice because I am generating an exception to determine if the value is IsNumeric:
public bool IsNumeric(string input)
{
try
{
int.Parse(input);
return true;
}
catch
{
return false;
}
}
Is this still the best way to approach this problem or is there a more efficient way to determine if a value is numeric in C#?
Try this:
int temp;
return int.TryParse(input, out temp);
Of course, the behavior will be different from Visual Basic IsNumeric. If you want that behavior, you can add a reference to "Microsoft.VisualBasic" assembly and call the Microsoft.VisualBasic.Information.IsNumeric function directly.
You can use extension methods to extend the String type to include IsInteger:
namespace ExtensionMethods
{
public static class MyExtensions
{
public static bool IsInteger(this String input)
{
int temp;
return int.TryParse(input, out temp);
}
}
}
Rather than using int.Parse, you can use int.TryParse and avoid the exception.
Something like this
public static bool IsNumeric(string input)
{
int dummy;
return int.TryParse(input, out dummy);
}
More generically you might want to look at double.TryParse.
One thing you should also consider is the potential of handling numeric string for different cultures. For example Greek (el-GR) uses , as a decimal separator while the UK (en-GB) uses a .. So the string "1,000" will either be 1000 or 1 depending on the current culture. Given this, you might consider providing overloads for IsNumeric that support passing the intended culture, number format etc. Take a look at the 2 overloads for double.TryParse.
I've used the following extension method before, if it helps at all:
public static int? AsNumeric(this string source)
{
int result;
return Int32.TryParse(source, out result) ? result : (int?)null;
}
Then you can use .HasValue for the bool you have now, or .Value for the value, but convert just once...just throwing it out there, not sure what situation you're using it for afterwards.
If you use Int32.TryParse then you don't need to wrap the call in a TryCatch block, but otherwise, yes that is the approach to take.
Not exactly crazy about this approach, but you can just call the vb.net isNumeric function from C# by adding a reference to the Microsoft.VisualBasic.dll library...
bool x= Microsoft.VisualBasic.Information.IsNumeric("123");
The other approaches given are superior, but wanted to add this for the sake of completeness.
Lot's of TryParse answers. Here's something a bit different using Char.IsNumber():
public bool IsNumeric(string s)
{
for (int i = 0; i < s.Length; i++)
{
if (char.IsNumber(s, i) == false)
{
return false;
}
}
return true;
}
Take a look on the following answer:
What is the C# equivalent of NaN or IsNumeric?
Double.TryParse takes care of all numeric values and not only ints.
Another option - LINQ!
public static class StringExtensions
{
public static bool IsDigits(this String text)
{
return !text.Any(c => !char.IsDigit(c));
}
}
Note that this assumes you only want digits 0-9. If you want to accept decimal point, sign, exponent, etc, then repalce IsDigit() with IsNumber().
I've been using the following small code snippet for years as a pure C# IsNumeric function.
Granted, it's not exactly the same as the Microsoft.VisualBasic library's IsNumeric function as that (if you look at the decompiled code) involves lots of type checking and usage of the IConvertible interface, however this small function has worked well for me.
Note also that this function uses double.TryParse rather than int.TryParse to allow both integer numbers (including long's) as well as floating point numbers to be parsed. Also note that this function specifically asserts an InvariantCulture when parsing (for example) floating point numbers, so will correctly identify both 123.00 and 123,00 (note the comma and decimal point separators) as floating point numbers.
using System;
using System.Globalization;
namespace MyNumberFunctions
{
public static class NumberFunctions
{
public static bool IsNumeric(this object expression)
{
if (expression == null)
{
return false;
}
double number;
return Double.TryParse(Convert.ToString(expression, CultureInfo.InvariantCulture), NumberStyles.Any, NumberFormatInfo.InvariantInfo, out number);
}
}
}
Usage is incredibly simple, since this is implemented as an extension method:
string myNumberToParse = "123.00";
bool isThisNumeric = myNumberToParse.IsNumeric();
public bool IsNumeric(string input)
{
int result;
return Int32.TryParse(input,out result);
}
try this:
public static bool IsNumeric(object o)
{
const NumberStyles sty = NumberStyles.Any;
double d;
return (o != null && Double.TryParse(o.ToString(), sty, null, out d));
}
You can still use the Visual Basic function in C#. The only thing you have to do is just follow my instructions shown below:
Add the reference to the Visual Basic Library by right clicking on your project and selecting "Add Reference":
Then import it in your class as shown below:
using Microsoft.VisualBasic;
Next use it wherever you want as shown below:
if (!Information.IsNumeric(softwareVersion))
{
throw new DataException(string.Format("[{0}] is an invalid App Version! Only numeric values are supported at this time.", softwareVersion));
}
Hope, this helps and good luck!

Categories