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);
Related
I have a txt file where from I can extract two strings (type and value). But, I need to cast it to the correct type. See the code bellow.
string type;
string value;
//example 1 //from the txt file
type = "int";
value = "25";
//example 2
type = "double";
value = "1.3";
//example 3
type = "string";
value = "blablabla";
//conversion I would like to do:
dynamic finalResult = (type)element.Value; //this returns an error
I need to do something like this, but I don't know to create a object type from the content of the string.
I tried to declare a Type:
Type myType = type;
But I dont know how to do it correctly.
In the name of clarity and type safety I think you should just use a combination of a switch expression and the various .TryParse() methods, having it return a generic type
static T? ReadVariable<T>(string type, string value) =>
type switch
{
"int" => int.TryParse(value, out int val) ? val : null, //null or throw an ex
"double" => double.TryParse(value, out double val) ? val : null,
"string" => string.TryParse(value, out string val) ? val : null,
"bool" => bool.TryParse(value, out bool val) ? val : null,
//... etc
_ => throw new NotSupportedException("This type is currently not supported")
};
int? num = ReadVariable<int>("int", "99"); //nullable return
//nullable handling
int num = ReadVariable<int>("int", "99") ?? default(int); //int type's default value is 0
int num = ReadVariable<int>("int", "99").GetValueOrDefault(-1); //default to an int value of your choice
Are you really going to have a situation where you need to parse out any type under the sun? This method allows you to maintain full control over what happens. Use of dynamic may potentially be way more headache than you expect
Update: thanks to #ckuri for pointing out that you may also want to use the try parse overload that allows for invariant culture in order to account for international numbering schemes
Update 2: added an examples of nullable handling
does this work?
object result;
string value = "some value";
string type = "some type";
switch(type)
{
case "int":
result = Convert.ToInt32(value);
break;
case "double":
result = Convert.ToDouble(value);
break;
case "string":
result = value;
break;
// case "any other datatype":
// result = convert explicitly to that datatype
}
I wanted to create a function, which will check the value of the parameter, if it's null it should set the value based on type of the parameter, else it should just return the value as it is.Here what i have tried.
public static T ConvertNull<T>(T obj)
{
if (String.IsNullOrEmpty(obj.ToString()))
{
HttpContext.Current.Response.Write("COMING IN");
if (typeof(T) == typeof(Int32))
{
return (T)Convert.ChangeType(0, typeof(T));
}
else if (typeof(T) == typeof(DateTime))
{
return (T)Convert.ChangeType(DateTime.Now, typeof(T));
}
else
{
return (T)Convert.ChangeType(String.Empty, typeof(T));
}
}
else
{
HttpContext.Current.Response.Write("ELSE");
return obj;
}
}
But the problem is it always goes in ELSE section and returns Junk value.
Can anyone tell me what's wrong with the above function.
String.IsNullOrEmpty(obj.ToString()) is very rarely going to be true. THe only thing I can think of that will generate an empty string vi ToString() is another empty string. In fact unless ToString() has been overridden (like it has been for native types like DateTime and int, you will get the fully qualified name of the object.
maybe you want
if (obj == default(T))
?
If you have a nullable type that you want to replace with some value in the event that it is null, and return the existing value in the event that it is not-null, there is alerady an existing operator that does this, the ?? operator:
int? i = null; //note of course that a non-nullable int cannot be null
int n = i ?? 0; //equals zero
string s = null;
string s2 = s ?? ""; //equals an empty string
string s3 = "hi";
string s4 = s3 ?? ""; //equals "hi"
Conveniently the ?? operator will not even compile in the event that the first operand's type is not nullable.
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).
I've got a generic type T. Using Marc's Operator class I can perform calculations on it.
Is it possible to detect by mere calculations whether the type is an integral or a nonintegral type?
Perhaps there is a better solution? I'd prefer to support any possible type, so I'd like to prevent hard-coding which types are integral/nonintegral.
Background info
The situation I find myself in is I want to cast a double to T but round to the nearest value of T to the double value.
int a = (int)2.6 results in 2 while I want it to result it in 3, without knowing the type (in this case int). It could also be double, in which case I want the outcome to be 2.6.
Have you tried Convert.ChangeType? Something like:
Convert.ChangeType(1.9d, typeof (T))
It will work for all numeric types I think (as long as the first parameter is iConvertible and the type is a supported one which all basic numerics should be I believe).
Its important to mention that this will call something like double.ToInt32 which rounds values rather than truncates (bankers rounding I believe).
I tested this in a little LinqPad program and it does what I think you want:
void Main()
{
var foo = RetNum<decimal>();
foo.Dump();
}
public static T RetNum<T>()
{
return (T)Convert.ChangeType(1.9d, typeof (T));
}
Here's a method which will determine if a particular value stored in a generic numeric type is an integer without hardcoding. Tested working for me on .NET 4. Correctly handles all built in numeric types (as defined in the MSDN link at the bottom) except BigInteger, which doesn't implement IConvertible.
public static bool? IsInteger<T>(T testNumber) where T : IConvertible
{
// returns null if T is non-numeric
bool? isInt = null;
try
{
isInt = testNumber.ToUInt64(CultureInfo.InvariantCulture) == testNumber.ToDouble(CultureInfo.InvariantCulture);
}
catch (OverflowException)
{
// casting a negative int will cause this exception
try
{
isInt = testNumber.ToInt64(CultureInfo.InvariantCulture) == testNumber.ToDouble(CultureInfo.InvariantCulture);
}
catch
{
// throw depending on desired behavior
}
}
catch
{
// throw depending on desired behavior
}
return isInt;
}
Here's a method which will determine whether a particular type is an integral type.
public static bool? IsIntegerType<T>() where T : IConvertible
{
bool? isInt = null;
try
{
isInt = Math.Round((double)Convert.ChangeType((T)Convert.ChangeType(0.1d, typeof(T)),typeof(double)), 1) != .1d;
// if you don't round it and T is float you'll get the wrong result
}
catch
{
// T is a non numeric type, or something went wrong with the activator
}
return isInt;
}
Convert.ChangeType is the way to convert, with rounding, between two generic numeric types. But for kicks and curiosity, here's a way to convert a generic numeric type to an int, which could be extended to return a generic type without too much difficulty.
public static int GetInt32<T>(T target) where T : IConvertible
{
bool? isInt = IsInteger<T>(target);
if (isInt == null) throw new ArgumentException(); // put an appropriate message in
else if (isInt == true)
{
try
{
int i = target.ToInt32(CultureInfo.InvariantCulture);
return i;
}
catch
{ // exceeded size of int32
throw new OverflowException(); // put an appropriate message in
}
}
else
{
try
{
double d = target.ToDouble(CultureInfo.InvariantCulture);
return (int)Math.Round(d);
}
catch
{ // exceeded size of int32
throw new OverflowException(); // put an appropriate message in
}
}
}
My results:
double d = 1.9;
byte b = 1;
sbyte sb = 1;
float f = 2.0f;
short s = 1;
int i = -3;
UInt16 ui = 44;
ulong ul = ulong.MaxValue;
bool? dd = IsInteger<double>(d); // false
bool? dt = IsInteger<DateTime>(DateTime.Now); // null
bool? db = IsInteger<byte>(b); // true
bool? dsb = IsInteger<sbyte>(sb); // true
bool? df = IsInteger<float>(f); // true
bool? ds = IsInteger<short>(s); // true
bool? di = IsInteger<int>(i); // true
bool? dui = IsInteger<UInt16>(ui); // true
bool? dul = IsInteger<ulong>(ul); // true
int converted = GetInt32<double>(d); // coverted==2
bool? isd = IsIntegerType<double>(); // false
bool? isi = IsIntegerType<int>(); // true
Additionally, this MSDN page has some example code which might be helpful. Specifically, it includes a list of types considered to be numeric.
I'm not 100% sure what you're asking, but:
To check if it's an integral type, use this: if (obj is float || obj is double), or if typeof(T) == typeof(float) || typeof(T) == typeof(double))
To check if it's an integral value, cast it to a double, and then do if(value == Math.Round(value))
Of course, that is assuming that you have a number in the first place. I believe that the Operator class you're using supports things like DateTime. Would it be better to make your generic method have a generic constraint where T : IConvertible? That way there'd be explicit ToDouble and ToInteger methods.
Edit:
I think I understand: you've got two local variables, double d; T num;. You want to cast d to type T, but with proper rounding if T is a integral type. Is that correct?
Assuming that's correct, here's what I'd do:
public void SomeMethod<T>()
{
double d;
// I think I got all the floating-point types. There's only a few, so we can test for them explicitly.
if(typeof(T) != typeof(double) && typeof(T) != typeof(float) && typeof(T) != typeof(Decimal))
{
d = Math.Round(d);
}
T converted = Convert.ChangeType(d, typeof(T));
}
Chris's answer gives a possible solution to the scenario I mentioned, but for performance reasons I am still attempting to answer the actual question.
The assumption (untested) is, Convert.ChangeType is much slower than Math.Round(). Ideally, I can check one time whether the given type is integral or not, and conditionally call Math.Round() from then on to obtain a much more efficient solution than calling Convert.ChangeType() constantly.
I'm attempting the following implementation:
Convert both 3, 2 and 1 to the desired unknown type. (This assumes a conversion from an int to the numeric type is possible, which should always be possible anyhow.)
In case 3 / 2 == 1, it is an integral type. Otherwise, it is a nonintegral type.
This solution doesn't rely anywhere on knowing the type and solely uses conversions and calculations.
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.