Convert string to nullable type (int, double, etc...)
Solution 1
Another thing to keep in mind is that the string itself might be null.
public static Nullable<T> ToNullable<T>(this string s) where T: struct
{
Nullable<T> result = new Nullable<T>();
try
{
if (!string.IsNullOrEmpty(s) && s.Trim().Length > 0)
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
result = (T)conv.ConvertFrom(s);
}
}
catch { }
return result;
}
Solution 2
You could try using the below extension method:
public static T? GetValueOrNull<T>(this string valueAsString)
where T : struct
{
if (string.IsNullOrEmpty(valueAsString))
return null;
return (T) Convert.ChangeType(valueAsString, typeof(T));
}
This way you can do this:
double? amount = strAmount.GetValueOrNull<double>();
int? amount = strAmount.GetValueOrNull<int>();
decimal? amount = strAmount.GetValueOrNull<decimal>();
Solution 3
What about this:
double? amount = string.IsNullOrEmpty(strAmount) ? (double?)null : Convert.ToDouble(strAmount);
Of course, this doesn't take into account the convert failing.
Solution 4
I wrote this generic type converter. It works with Nullable and standard values, converting between all convertible types - not just string. It handles all sorts of scenarios that you'd expect (default values, null values, other values, etc...)
I've been using this for about a year in dozens of production programs, so it should be pretty solid.
public static T To<T>(this IConvertible obj)
{
Type t = typeof(T);
if (t.IsGenericType
&& (t.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
if (obj == null)
{
return (T)(object)null;
}
else
{
return (T)Convert.ChangeType(obj, Nullable.GetUnderlyingType(t));
}
}
else
{
return (T)Convert.ChangeType(obj, t);
}
}
public static T ToOrDefault<T>
(this IConvertible obj)
{
try
{
return To<T>(obj);
}
catch
{
return default(T);
}
}
public static bool ToOrDefault<T>
(this IConvertible obj,
out T newObj)
{
try
{
newObj = To<T>(obj);
return true;
}
catch
{
newObj = default(T);
return false;
}
}
public static T ToOrOther<T>
(this IConvertible obj,
T other)
{
try
{
return To<T>(obj);
}
catch
{
return other;
}
}
public static bool ToOrOther<T>
(this IConvertible obj,
out T newObj,
T other)
{
try
{
newObj = To<T>(obj);
return true;
}
catch
{
newObj = other;
return false;
}
}
public static T ToOrNull<T>
(this IConvertible obj)
where T : class
{
try
{
return To<T>(obj);
}
catch
{
return null;
}
}
public static bool ToOrNull<T>
(this IConvertible obj,
out T newObj)
where T : class
{
try
{
newObj = To<T>(obj);
return true;
}
catch
{
newObj = null;
return false;
}
}
Solution 5
You might want to try:
TypeConverter conv = TypeDescriptor.GetConverter(typeof(int));
conv.ConvertFrom(mystring);
do your own null check and return int?
if necessary. You'll also want to wrap that in a try {}
Nathan Koop
I'm currently a Sr. Dev/tech lead at Bold Commerce. I work with PHP, Laravel, Eloquent, React, Redux, GoLang, MySQL and more.
Updated on July 08, 2022Comments
-
Nathan Koop almost 2 years
I am attempting to do some data conversion. Unfortunately, much of the data is in strings, where it should be int's or double, etc...
So what I've got is something like:
double? amount = Convert.ToDouble(strAmount);
The problem with this approach is if strAmount is empty, if it's empty I want it to amount to be null, so when I add it into the database the column will be null. So I ended up writing this:
double? amount = null; if(strAmount.Trim().Length>0) { amount = Convert.ToDouble(strAmount); }
Now this works fine, but I now have five lines of code instead of one. This makes things a little more difficult to read, especially when I have a large amount of columns to convert.
I thought I'd use an extension to the string class and generic's to pass in the type, this is because it could be a double, or an int, or a long. So I tried this:
public static class GenericExtension { public static Nullable<T> ConvertToNullable<T>(this string s, T type) where T: struct { if (s.Trim().Length > 0) { return (Nullable<T>)s; } return null; } }
But I get the error: Cannot convert type 'string' to 'T?'
Is there a way around this? I am not very familiar with creating methods using generics.
-
bdukes about 15 yearsIf you cast either of the return values to a double? (or int?, etc), then it will be able to convert them to the final double?. See the change above.
-
Michael Meadows about 15 yearsYou can omit the "T type" parameter since it's not used.
-
LukeH about 15 years+1, Just beat me to it. A small nitpick: the converted value needs to be assigned directly to result, not to result.Value. ie, "result = (T)conv.ConvertFrom(s);".
-
John Kraft about 15 yearsSorry about that. Always forget the cast until the compiler screams. :)
-
RichardOD almost 15 yearsLuke- that's a little more than a nitpick- the code doesn't compile unless you do this!
-
TheSoftwareJedi almost 15 yearsSee my answer below which handles nullable and standard types in the same methods. Also provides a boatload more options... :)
-
Zaffiro almost 15 yearsIMHO this is the most elegant solution to the problem
-
Sergej Andrejev over 13 yearsThis can be simplified a bit with string.IsNullOrWhiteSpace() if you use .Net4
-
AaronHS over 12 yearsactually.. this solution doesn't work. changetype doesn't convert to nullable types. instead use typeconverter
-
Pavel Hodek over 11 yearsWho was downvoting please add a comment what's wrong with this universal solution.
-
Paul Groke over 11 yearsI don't think ignoring all conversion errors is the right thing to do. Also you should probably not swallow all kinds of exceptions. At least re-throw
OutOfMemoryException
if you cannot narrow it down to a fixed set of exception types. -
Paul Groke over 11 yearsWell, first there's something very wrong with your answer, and that's the "you can forget all other answers". Which would be wrong even if it were true (which it is not). And what's wrong with the "universal solution" is that it's full of bad performance (
typeName.IndexOf
? really?) and strang behaviour (the shownTryConvert
function doesn't even handle null values correctly). -
Steve over 9 yearsthis will fail if you aren't null and you try amount.HasValue and declare amount as var.
-
minerva over 8 years@andrefadila - To use: string sampleVendorId = ""; int? vendorId = sampleVendorId.ToNullable<int>();
-
rayzinnz about 8 yearsHi thanks this solved it for me. FYI I was using VB.NET, and the VB equivilant
CType(Object, Nullable(Of Double))
works fine with strings -
David over 7 yearsThe call conv.ConvertFrom doesn't convert a nullable type of T, which makes this function a little counter intuitive. You don't need a try catch in this function. These three lines of code makes it all: if (string.IsNullOrWhiteSpace(stringObject)) return null; var conv = TypeDescriptor.GetConverter(typeof(T)); return (T?)conv.ConvertFrom(stringObject);
-
Arci over 6 yearsUse result = (T)Convert.ChangeType(s, typeof(T), System.Globalization.CultureInfo.InvariantCulture); for conversion from object. TypeConverter.convertFrom does not support conversion between decimal and int.
-
S.Serpooshan almost 6 years@DaveWut No, if we the string is entered by user, it may be an invalid number like as "abc1357" instead of "1357". So we need to check if conversion fails...
-
S.Serpooshan almost 6 years@JoelCoehoorn Good code! but I think we could do it also without using those try/catch block and GetConverter codes... as in my answer
-
Marcus.D almost 5 yearsThat's what I need to know... I have to use the underlying type of a Nullable-Type when using the Convert.ChangeType-Method. Because it don't works with a Nullable-Typ for parameter conversionType.
-
S.Serpooshan about 4 years@MassimilianoKraus may be, but it is a simple 12 lines code, written once, but using all the times. And, as I said, it should/may be faster than using those
TypeDescriptor.GetConverter
... codes. This is just another way. -
wazz about 4 yearsis there a version of your first example that can be used with strings?