Is there any generic Parse() function that will convert a string to any type using parse?
I want to conve开发者_StackOverflow中文版rt a string to a generic type like int
or date
or long
based on the generic return type.
Basically a function like Parse<T>(String)
that returns an item of type T
.
For example if a int was passed the function should do int.parse
internally.
System.Convert.ChangeType
As per your example, you could do:
int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));
To satisfy your "generic return type" requirement, you could write your own extension method:
public static T ChangeType<T>(this object obj)
{
return (T)Convert.ChangeType(obj, typeof(T));
}
This will allow you to do:
int i = "123".ChangeType<int>();
Well looks like I am too late for answering on this thread. But here is my implementation:
Basically, I have created an Extention method for the Object class. It handles all the types, i.e nullable, classes, and struct.
public static T ConvertTo<T>(this object value)
{
T returnValue;
if (value is T variable)
returnValue = variable;
else
try
{
//Handling Nullable types i.e, int?, double?, bool? .. etc
if (Nullable.GetUnderlyingType(typeof(T)) != null)
{
TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
returnValue = (T) conv.ConvertFrom(value);
}
else
{
returnValue = (T) Convert.ChangeType(value, typeof(T));
}
}
catch (Exception)
{
returnValue = default(T);
}
return returnValue;
}
cleaner version of Pranay's answer
public static T ConvertTo<T>(this object value)
{
if (value is T variable) return variable;
try
{
//Handling Nullable types i.e, int?, double?, bool? .. etc
if (Nullable.GetUnderlyingType(typeof(T)) != null)
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
}
return (T)Convert.ChangeType(value, typeof(T));
}
catch (Exception)
{
return default(T);
}
}
System.Convert.ChangeType
does not convert to any type. Think of the following:
- nullable types
- enums
- Guid etc.
These conversions are possible with this implementation of ChangeType.
There are a couple of conventions in the .NET to convert objects of one type to another.
- Convert.ChangeType if the type implements IConvertible
- TypeDescriptor.GetConverter if the type has a TypeConverterAttribute
But these methods are much slower than your typical T.Parse(string)
, cause boxing and involve lots of allocations each time you want to convert a single value.
For ValueString, I chose to find a suitable, static parsing method of the type using reflection, build a lambda expression calling it and cache the compiled delegate for future use (See this answer for an example).
It also fallbacks to the ways I mentioned above if the type doesn't have a suitable parsing method (See the performance section in the readme).
var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
As of C# 11 and .Net 7, this is now possible and supported thanks to static methods on interfaces.
The new IParsable<TSelf> provides a static Parse method:
abstract static TSelf Parse(string s, IFormatProvider? provider);
All the common value types (int, decimal, Guid, etc) implement this interface, but with one exception: Nullable<T>
doesn't, as obviously the T
in nullable cannot be assumed to implement IParsable<T>
. But this shouldn't be an issue in practice (example provided below).
Here's a simple extension method to make use of it:
public static T Parse<T>(this string s, IFormatProvider? provider = null) where T : IParsable<T>
{
return T.Parse(s, provider);
}
So, for example, a call of myString.Parse<int>
will directly call int.Parse
without boxing, or the need for checking the type at runtime.
Example usage:
string s = "5";
int i = s.Parse<int>();
double d = s.Parse<double>();
// Need Nullable<T> support? Just use the null-conditional operator.
string? s2 = null;
decimal? d2 = s2?.Parse<decimal>();
精彩评论