How to call a function based on string value in C# - c#

I want to convert a string to specific type based on the value of other string
Suppose I have two strings str1, str2.
If str2 is double then I want to call convert.ToDouble(str1) and return the Double value. Is there any way to accomplish this?
I tried using reflections (using methodInfo object to invoke)
But still it returns again an object for which I need to convert.
Please help..

Use the double.TryParse Method.
The method attempts to convert a string to a double and if it fails it returns false.
If I'm understanding you correctly, this is what you want:
private static double ConditionalConvertToDouble(string str1, string str2) {
double converted;
if (double.TryParse(str2, out converted)) {
// str2 can be converted to a double, so return str1 converted to a double.
return Convert.ToDouble(str1);
} else {
// I'm throwing an exception here if str1 cannot be converted to a double; you
// might want to do something different.
throw new ArgumentException("str1 cannot be converted to a double");
}
}
Call the method like this:
var d = ConditionalConvertToDouble("11", "22");

double result;
Double.TryParse(str1, out result);
if str1 is double, result will have its value, otherwise result will have 0. It will not throw any exception.
Hope it helps.

The following method will attempt to get the double value from "str1" if and only if "str2" also represents a double. If either of the numbers are not doubles, it will return double.NaN.
This method avoids throwing exceptions, but still allows you to check if you have a valid number.
public double GetFirstDoubleIfSecond(string str1, string str2)
{
double myDouble;
if(double.TryParse(str2, out myVal) && double.TryParse(str1, out myVal))
{
return myDouble
}
return double.NaN;
}
If you are expecting NaN values in your string, then you can use the following method, which will throw an exception if either of the strings are not doubles. Otherwise, it will return the string value represented in "str1".
public double GetFirstDoubleIfSecondWithExceptions(string str1, string str2)
{
double.Parse(str2);
return double.Parse(str1);
}

I think that switch-case operator should help to you. You should to specify some cases depending on one of your input string and make right decision. Your method should return object, if you really don't know which type exactly will return your method.
public object MyMethod(string str1, string str2)
{
switch(something)
{
case 1:
case 2:
return double.Parse(str1);
break;
case 3:
case 4:
return int.Parse(str1);
break;
default
return null;
}
}
where something is the criterion you should to specify.
After that System.Object.GetType() method can help you to detirmine which type was returned by your method.

Related

Format function - VB6 to C# conversion

What is the C# equivalent of:
Public stringValue As String
Public intValue As Integer
intValue = Format(val(stringValue), "00")
?
So the vb6 Format function converts to string and the Val function converts to a number. If you look at the Microsoft documentation for Val:
Val(" 1615 198th Street N.E.")
// returns
1615198
in c# this can clumsily be converted to
string stringValue = " 1615 198th Street N.E.";
// assign to int if int wanted
// throws exception if cannot be converted to int, use Int32.TryParse if you want to handle that
int intValue = System.Convert.ToInt32(
new string(stringValue.Replace(" ", "").TakeWhile(System.Char.IsDigit).ToArray())
);
System.Console.WriteLine(intValue);
it's really going to depend on what your expectations are for what stringValue is going to be and what you want returned. Also I don't think you can assign a string value to an int so willy nilly like you can in vb6. It can definitely be cleaned up but that just depends on what you're doing.
edit:
Since you're testing a stringValue = "3" this should work
string stringVal = "3";
if(!System.Int32.TryParse(stringVal, out int intValue))
{
System.Console.WriteLine($"value={stringVal} not of type int");
}
return intValue;
If truly replicating the VB6 Val function is desired, then Microsoft.VisualBasic.Val can be used. It is pretty faithful to the original, and of course can be called from C#.
See https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.conversion.val?view=netcore-3.1#Microsoft_VisualBasic_Conversion_Val_System_String_ for the string overload (returns Double).
One aspect where it doesn't return the same result as VB6 is for a string like "3.4.5". VB6 Val will return 34.5, while the .Net Val will return 3.4.
No need for exception handling (just like with VB6), if the input can't be converted to a number, no exception is thrown (well, mostly, there are some edge cases) or error returned, the return value is zero.

Converter doesn't convert culture number format?

I have a string number in my C# program, it's "6.967.015". That's the german number format where "." seperates the 1000-groups and "," is the decimal seperator.
I made a function that uses Double.TryParse to convert the text to a double value. It works fine:
if (Double.TryParse(text, out result))
{
return result;
}
else
{
return defaultValue;
}
Now I needed a second type to be convertable and instead of copying the function, I wanted to make a function that accepts the type (don't mind the Type argument instead of generic <T> function, it's for integrity reasons).
public static object DefaultIfNotValid(this object value, Type type, object defaultValue)
{
var converter = TypeDescriptor.GetConverter(type);
object convertedValue;
if (converter != null)
{
try
{
convertedValue = converter.ConvertFrom(value);
return convertedValue;
}
catch (Exception)
{
return defaultValue;
}
}
return defaultValue;
}
The problem with this code is that it works for "123" but it doesn't work for the above number "6.967.015". The Convert function throws "6.967.015 is not a valid value for double". I tried giving the function a culture parameter to see if that was the problem, but that didn't work either (I passed null for the TypeDescriptorContext).
converter.ConvertFrom(null, new CultureInfo("de-de"), value);
That still threw the same exception. I also tried a custom culture with explicitly set group and decimal seperator, but still the same issue.
Maybe it's not even the culture but something else that the converter doesn't like about the value.
Does anyone know what could be the cause of this? Even though the string converts just fine with an explicit double.TryParse call.
You can try like this:
var nf = new NumberFormatInfo{NumberDecimalSeparator = ",", NumberGroupSeparator = "."};
var convertedValue = Convert.ToDouble(value, nf);
If TryParse method works use "method overload", default value for failed converting will be target type indicator in your case
Create own converting method for every type you want to convert
public static double DefaultIfNotValid(this string value, double defaultValue)
{
double temp = 0;
if (double.TryParse(value, out temp) == true)
return temp;
return defaultValue;
}
public static int DefaultIfNotValid(this string value, int defaultValue)
{
int temp = 0;
if (int.TryParse(value, out temp) == true)
return temp;
return defaultValue;
}
Then using seems not so painful
string rawValue = "6.967.015";
double defaultValue = 9.9;
double parsedValue = rawValue.DefaultIfNotValid(defaultValue);

Using double.Parse with a null value

Below is my statement:
double? My_Value = null;
if (Request.Form["MyValue"] != null)
My_Value = double.Parse(Request.Form["MyValue"].ToString());
When I try to submit my form with no value for 'MyValue' I get a run time error saying 'Input string was not in a correct format.'. When I try to use:
My_Value = double.TryParse(Request.Form["MyValue"].ToString());
Visual Studio gives me a compile error that says 'No overload for method 'TryParse' takes 1 arguments'.
When I provide a value for 'My_Value', the form submits. How do I get the program to accept a null value? Thank you.
You need to declare a double variable to store the result and pass it to TryParse as an out argument, so it will be assigned if the parse succeeded:
double result;
var isValid = double.TryParse(Request.Form["MyValue"].ToString(), out result);
Also TryParse is different than Parse method, it doesn't return a numerical result, it returns a boolean result that indicates whether the parsing is succeeded or not.So you need to assign that result and check it's value to make sure parsing was successful.Or you could directly check the result without storing it in a variable.
double result;
double? My_Value = double.TryParse(Request.Form["MyValue"].ToString(), out result)
? (double?)result
: null;
Both solutions will result in 0;
string myString = null;
double result = Convert.ToDouble(myString);
OR
string myString = null;
double result = double.Parse(myString ?? "0");
The problem with your first case isn't just about handling nulls but rather about handling anything that cannot be parsed (since you are accepting a value from an untrustworthy source). Using TryParse is the way to go here.
However, the TryParse method accepts two arguments, the first the value to parse, the second a value to assign to if parsing succeeds (as an out) parameter.
For just such an occasion whereby you'd like a nullable result, a custom utility method can come in handy:
public static class NullableDouble
{
public static double? TryParse(string input)
{
double result;
var success = double.TryParse(input, out result);
return success ? result as double? : null;
}
}
Useable like so:
var myValue = NullableDouble.TryParse((Request.Form["MyValue"] ?? string.Empty).ToString());
The signature for TryParse is bool TryParse(string str, out double result)
Use it like this:
double result;
var success = double.TryParse(Request.Form["MyValue"].ToString(), out result);
My_Value = success? result : 0d;
As "usr" mentioned in the comments, the next time you get an error like this, you should check the MSDN documentation first before coming here.

Which is faster, Convert.ToXX() or xx.Parse(yy.ToString())?

I'm trying to make a method faster. Right now, it takes an object obj and converts it to a double with the following:
double val = Convert.ToDouble(obj);
Would it be faster if I did this?
double val = double.Parse(obj.ToString());
For string Convert.ToDouble just checks value for null and return 0.0 if so. Then it really calls double.Parse:
[__DynamicallyInvokable]
public static double ToDouble(object value)
{
if (value != null)
return ((IConvertible) value).ToDouble((IFormatProvider) null);
else
return 0.0;
}
// common implementation of IConvertable
double IConvertible.ToDouble(IFormatProvider provider)
{
return Convert.ToDouble(this, provider);
}
// implementation for string
[__DynamicallyInvokable]
public static double ToDouble(string value, IFormatProvider provider)
{
if (value == null)
return 0.0;
else
return double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
}
// and for long. differs, right?
[__DynamicallyInvokable]
public static double ToDouble(long value)
{
return (double) value;
}
So I don't think that double.Parse if much faster for non-number types. But when you don't really know that type your argument is, it's better to call Convert.ToDouble(value) instead of double.Parse(value.ToString()).
Convert.ToDouble() actually wraps a double.Parse() call so the difference in speed is negligible.
In theory the first, as you're making a single call. The second example you're calling the Parse method and then passing it the result of the ToString method.
That being said, see some of the comments as to why there maybe better solutions (i.e. what if it fails).

Better way to cast object to int

This is probably trivial, but I can't think of a better way to do it. I have a COM object that returns a variant which becomes an object in C#. The only way I can get this into an int is
int test = int.Parse(string.Format("{0}", myobject))
Is there a cleaner way to do this? Thanks
You have several options:
(int) — Cast operator. Works if the object already is an integer at some level in the inheritance hierarchy or if there is an implicit conversion defined.
int.Parse()/int.TryParse() — For converting from a string of unknown format.
int.ParseExact()/int.TryParseExact() — For converting from a string in a specific format
Convert.ToInt32() — For converting an object of unknown type. It will use an explicit and implicit conversion or IConvertible implementation if any are defined.
as int? — Note the "?". The as operator is only for reference types, and so I used "?" to signify a Nullable<int>. The "as" operator works like Convert.To____(), but think TryParse() rather than Parse(): it returns null rather than throwing an exception if the conversion fails.
Of these, I would prefer (int) if the object really is just a boxed integer. Otherwise use Convert.ToInt32() in this case.
Note that this is a very general answer: I want to throw some attention to Darren Clark's response because I think it does a good job addressing the specifics here, but came in late and wasn't voted as well yet. He gets my vote for "accepted answer", anyway, for also recommending (int), for pointing out that if it fails (int)(short) might work instead, and for recommending you check your debugger to find out the actual runtime type.
The cast (int) myobject should just work.
If that gives you an invalid cast exception then it is probably because the variant type isn't VT_I4. My bet is that a variant with VT_I4 is converted into a boxed int, VT_I2 into a boxed short, etc.
When doing a cast on a boxed value type it is only valid to cast it to the type boxed.
Foe example, if the returned variant is actually a VT_I2 then (int) (short) myObject should work.
Easiest way to find out is to inspect the returned object and take a look at its type in the debugger. Also make sure that in the interop assembly you have the return value marked with MarshalAs(UnmanagedType.Struct)
Convert.ToInt32(myobject);
This will handle the case where myobject is null and return 0, instead of throwing an exception.
Use Int32.TryParse as follows.
int test;
bool result = Int32.TryParse(value, out test);
if (result)
{
Console.WriteLine("Sucess");
}
else
{
if (value == null) value = "";
Console.WriteLine("Failure");
}
Maybe Convert.ToInt32.
Watch out for exception, in both cases.
var intTried = Convert.ChangeType(myObject, typeof(int)) as int?;
I am listing the difference in each of the casting ways. What a particular type of casting handles and it doesn't?
// object to int
// does not handle null
// does not handle NAN ("102art54")
// convert value to integar
int intObj = (int)obj;
// handles only null or number
int? nullableIntObj = (int?)obj; // null
Nullable<int> nullableIntObj1 = (Nullable<int>)obj; // null
// best way for casting from object to nullable int
// handles null
// handles other datatypes gives null("sadfsdf") // result null
int? nullableIntObj2 = obj as int?;
// string to int
// does not handle null( throws exception)
// does not string NAN ("102art54") (throws exception)
// converts string to int ("26236")
// accepts string value
int iVal3 = int.Parse("10120"); // throws exception value cannot be null;
// handles null converts null to 0
// does not handle NAN ("102art54") (throws exception)
// converts obj to int ("26236")
int val4 = Convert.ToInt32("10120");
// handle null converts null to 0
// handle NAN ("101art54") converts null to 0
// convert string to int ("26236")
int number;
bool result = int.TryParse(value, out number);
if (result)
{
// converted value
}
else
{
// number o/p = 0
}
There's also TryParse.
From MSDN:
private static void TryToParse(string value)
{
int number;
bool result = Int32.TryParse(value, out number);
if (result)
{
Console.WriteLine("Converted '{0}' to {1}.", value, number);
}
else
{
if (value == null) value = "";
Console.WriteLine("Attempted conversion of '{0}' failed.", value);
}
}
Strange, but the accepted answer seems wrong about the cast and the Convert in the mean that from my tests and reading the documentation too it should not take into account implicit or explicit operators.
So, if I have a variable of type object and the "boxed" class has some implicit operators defined they won't work.
Instead another simple way, but really performance costing is to cast before in dynamic.
(int)(dynamic)myObject.
You can try it in the Interactive window of VS.
public class Test
{
public static implicit operator int(Test v)
{
return 12;
}
}
(int)(object)new Test() //this will fail
Convert.ToInt32((object)new Test()) //this will fail
(int)(dynamic)(object)new Test() //this will pass
You can first cast object to string and then cast the string to int;
for example:
string str_myobject = myobject.ToString();
int int_myobject = int.Parse(str_myobject);
this worked for me.
int i = myObject.myField.CastTo<int>();
This worked for me, returning 0 also when myobject contains a DBNull
int i = myobject.ToString().Cast<int>().FirstOrDefault();

Categories

Resources