I feel that every time I use TryParse that it results in somewhat ugly code. Mainly I am using it this way:
int value;
if (!int.TryParse(someStringValue, out value))
{
value = 0;
}
Is there some more elegant solution for parsing all basic data types, to be specific is there a way to do fail safe parsing in one line? By fail safe I assume setting default value if parsing fails without exception.
By the way, this is for cases where I must do some action even if parsing fails, just using the default value.
This is valid and you may prefer it if you have a liking for single-liners:
int i = int.TryParse(s, out i) ? i : 42;
This sets the value of i to 42 if it cannot parse the string s, otherwise it sets i = i.
how about a direct extension method?
public static class Extensions
{
public static int? TryParse(this string Source)
{
int result;
if (int.TryParse(Source, out result))
return result;
else
return null;
}
}
or with the new c# syntax in a single line:
public static int? TryParse(this string Source) => int.TryParse(Source, out int result) ? result : (int?)null;
usage:
v = "234".TryParse() ?? 0
You can write your own methods for a solution that suits you better. I stumbled upon the Maybe class that wraps the TryParse methods a while ago.
int? value = Maybe.ToInt("123");
if (value == null)
{
// not a number
}
else
{
// use value.Value
}
or specify the default value in-line:
int value = Maybe.ToInt("123") ?? 0;
Observe the distinction between Nullable<int>/int? and int.
See http://www.kodefuguru.com/post/2010/06/24/TryParse-vs-Convert.aspx for more info
There is a nice little feature in C# 6 C# 7, Declaration expressions, so in C# 7 instead of:
int x;
if (int.TryParse("123", out x))
{
DoSomethingWithX(x);
}
we can use:
if (int.TryParse("123", out int x))
{
DoSomethingWithX(x);
}
Nice enough for me :)
using C# 7 in single line
int.TryParse(s, out var i) ? i : (int?)null;
Example Method:
public static int? TryParseSafe(string s)
{
return int.TryParse(s, out var i) ? i : (int?)null;
}
In your particular example, you can do this:
int value;
int.TryParse(someStringValue, out value);
...because Int32.TryParse() is documented as setting value=0 if it fails the parse.
You could use TypeDescriptor instead:
public T Convert<T>(string input, T defaultVal)
{
var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
if(converter != null)
{
return (T)converter.ConvertFromString(input);
}
return defaultVal;
}
public T Convert<T>(string input)
{
return Convert(input, default(T));
}
You could constrain T to struct and use Nullable also (as per #skarmats answer).
This is one of the nice surprises for C# developers who try F#.
The TryParse method returns a tuple containing both the bool and the value.
Related
I have an enum type like this as an example:
public Enum MyEnum {
enum1, enum2, enum3 };
I'll read a string from config file. What I need is to parse the string to MyEnum type or null or not defined. Not sure if the following code will work (sorry for not having access to my VS right now):
// example: ParseEnum<MyEnum>("ENUM1", ref eVal);
bool ParseEnum<T>(string value1, ref eVal) where T : Enum
{
bool bRet = false;
var x = from x in Enum.GetNames(typeof(T)) where
string.Equals(value1, x, StringComparison. OrdinalIgnoreCase)
select x;
if (x.Count() == 1 )
{
eVal = Enum.Parse(typeof(T), x.Item(0)) as T;
bRet = true;
}
return bRet;
}
Not sure if it is correct or there is any other simple way to parse a string to a MyEnum value?
What about something like:
public static class EnumUtils
{
public static Nullable<T> Parse<T>(string input) where T : struct
{
//since we cant do a generic type constraint
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Generic Type 'T' must be an Enum");
}
if (!string.IsNullOrEmpty(input))
{
if (Enum.GetNames(typeof(T)).Any(
e => e.Trim().ToUpperInvariant() == input.Trim().ToUpperInvariant()))
{
return (T)Enum.Parse(typeof(T), input, true);
}
}
return null;
}
}
Used as:
MyEnum? value = EnumUtils.Parse<MyEnum>("foo");
(Note: old version used try/catch around Enum.Parse)
private enum MyEnum
{
Enum1 = 1, Enum2 = 2, Enum3 = 3, Enum4 = 4, Enum5 = 5, Enum6 = 6,
Enum7 = 7, Enum8 = 8, Enum9 = 9, Enum10 = 10
}
private static Object ParseEnum<T>(string s)
{
try
{
var o = Enum.Parse(typeof (T), s);
return (T)o;
}
catch(ArgumentException)
{
return null;
}
}
static void Main(string[] args)
{
Console.WriteLine(ParseEnum<MyEnum>("Enum11"));
Console.WriteLine(ParseEnum<MyEnum>("Enum1"));
Console.WriteLine(ParseEnum<MyEnum>("Enum6").GetType());
Console.WriteLine(ParseEnum<MyEnum>("Enum10"));
}
OUTPUT:
//This line is empty as Enum11 is not there and function returns a null
Enum1
TestApp.Program+MyEnum
Enum10
Press any key to continue . . .
This is an old question, but now .NET 4.5 has Enum.TryParse<TEnum>().
I have a TryParseName method in UnconstrainedMelody, a library for delegate and enum utility methods which uses "inexpressible" constraints via some postbuild trickery. (Code using the library doesn't need a postbuild, just to be clear.)
You would use it like this:
Foo foo;
bool parsed = Enums.TryParseName<Foo>(name, out foo);
I don't currently have a case-insensitive version, but I could easily introduce one if you wanted. Note that this doesn't try to parse numbers e.g. "12" like the built-in version does, nor does it try to parse comma-separated lists of flags. I may add the flags version later on, but I can't see much point in the numeric version.
This is done without boxing and without execution time type checking. Having the constraint is really handy :)
Please let me know if you'd find a case-insensitive parse useful...
If you're using .NET 3.5 (or even 2.0, if you trim out the extension method), I've had great luck with the techniques in this article:
Enumerations and Strings - Stop the Madness!
EDIT: Domain is gone and is now a link farm. I pulled the code (slightly modified and added to over time) from our codebase at work, which you can now find here:
https://gist.github.com/1305566
You can use TryParse if you want to avoid using try/catch.
MyEnum eVal;
if (Enum.TryParse("ENUM2", true, out eVal)){
// now eVal is the enumeration element: enum2
}
//unable to parse. You can log the error, exit, redirect, etc...
I modified the selected answer a little bit. I hope you like it.
public static class EnumUtils
{
public static Nullable<T> Parse<T>(string input) where T : struct
{
//since we cant do a generic type constraint
if (!typeof(T).IsEnum)
{
throw new ArgumentException("Generic Type 'T' must be an Enum");
}
int intVal;
if (!string.IsNullOrEmpty(input) && !int.TryParse(input, out intVal))
{
T eVal;
if (Enum.TryParse(input, true, out eVal))
{
return eVal;
}
}
return null;
}
}
I have just combined the syntax from here, with the exception handling from here, to create this:
public static class Enum<T>
{
public static T Parse(string value)
{
//Null check
if(value == null) throw new ArgumentNullException("value");
//Empty string check
value = value.Trim();
if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value");
//Not enum check
Type t = typeof(T);
if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "TEnum");
return (T)Enum.Parse(typeof(T), value);
}
}
You could twiddle it a bit to return null instead of throwing exceptions.
To return Enum by string, if contains:
public static T GetEnum<T>(string s)
{
Array arr = Enum.GetValues(typeof(T));
foreach (var x in arr)
{
if (x.ToString().Contains(s))
return (T)x;
}
return default(T);
}
I am developing a generic wrapper around TryParse, as follows:
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? ParseOrNull<T>(this string value, ParseDelegate<T> parse) where T : struct
{
T result;
var parsed = parse(value, out result);
return parsed ? result : (T?)null;
}
[Test]
public void ParsesValidInt()
{
Assert.AreEqual(1234, "1234".ParseOrNull<int>(int.TryParse));
}
[Test]
public void ParsesValidDecimal()
{
Assert.AreEqual(12.34M, "12.34".ParseOrNull<decimal>(decimal.TryParse));
}
This is kinda repetitive. Is there a way to avoid mentioning int.TryParse at all, so that my calls look as follows:
"1234".ParseOrNull<int>()
Is there a way to avoid mentioning int.TryParse at all, so that my calls look as follows:
Not directly, as TryParse isn't part of a shared interface. If there were a shared interface to these value types, this would be possible via a constraint.
Personally, I would not suggest using extension methods for this. I would rather write this as something more like:
public static class Parse
{
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? FromString<T>(string value, ParseDelegate<T> parse) where T : struct
{
T result;
var parsed = parse(value, out result);
return parsed ? result : (T?)null;
}
public static int? ToNullableInt32(string value)
{
return FromString<int>(value, int.TryParse);
}
public static double? ToNullableDouble(string value)
{
return FromString<double>(value, double.TryParse);
}
}
This adds a bit of overhead up front, but allows you to write these very cleanly, ie:
int? first = Parse.FromString<int>("1234", int.TryParse);
int? second = Parse.ToNullableInt32("1234");
double? third = Parse.ToNullableDouble("1234");
I see little value in putting an extension method, especially on something like string (which is used everywhere), as it "pollutes" the compilation of string itself. You'll see this everywhere you use strings - basically, any time you use this namespace, you'll end up having these parse methods in your intellisense, etc. In addition, this seems more like a "utility" than something that should appear as built-in functionality of string itself, which is why I personally prefer a separate class for it.
In short no but you can add a new helper method:
public static int? ParseInt(this string value)
{
return value.ParseOrNull<int>(int.TryParse);
}
and then:
"1234".ParseInt();
Look at how Microsoft deals with several types . They provides one method for each type. Enumerable.Sum Method is a good example. If you want to simplify the calling code, you should provide the overloads for each types :
public static int? ParseOrNull<int>(this string value)
{
int result;
var parsed = int.TryParse(value, out result);
return parsed ? result : (T?)null;
}
public static long? ParseOrNull<long>(this string value)
{
long result;
var parsed = long.TryParse(value, out result);
return parsed ? result : (T?)null;
}
// same for ulong, long, uint, ushort, short, byte,
// bool, float, double, decimal. Do I forget one ?
I think it's more important to simplify calls than the method itself. In fact, there is not a huge number of types to deal with.
Yes, you can use Convert.ChangeType
public static T? ParseOrNull<T>(this string value) where T : struct, IConvertible
{
try
{
return (T)Convert.ChangeType(value, typeof(T));
}
catch (FormatException ex)
{
return null;
}
}
It wont have as good performance (use of try catch) as TryParse, but should work for all IConvertible types
The answer is a big YES. You're trying to exploit the existence of the static T.TryParse(string, out T) function on the types you're converting to, and we can do that pretty easily with a little reflection.
public static T? ParseOrNull<T>(this string str)
where T: struct, IConvertible
{
// find the TryParse method.
var parseMethod = typeof(T).GetMethod("TryParse",
// We want the public static one
BindingFlags.Public | BindingFlags.Static,
Type.DefaultBinder,
// where the arguments are (string, out T)
new[] { typeof(string), typeof(T).MakeByRefType() },
null);
if (parseMethod == null)
// You need to know this so you can parse manually
throw new InvalidOperationException(
string.Format("{0} doesn't have a TryParse(..) function!",
typeof(T).FullName));
// create the parameter list for the function call
var args = new object[] { str, default(T) };
// and then call the function.
if ( (bool)parseMethod.Invoke(null, args))
return (T?)args[1]; // if it returned true
// if it returned false
return null;
}
This is the original answer I provided, based on the idea that you need two different parse methods: One for value types and another for reference types.
public delegate bool ParseDelegate<T>(string s, out T result);
public static T? ParseOrNull<T>(this string str, ParseDelegate<T> Parse)
where T: struct
{
T result;
if (!Parse(str, out result))
return null;
return result;
}
public static T ParseOrNull<T>(this string str, ParseDelegate<T> Parse)
where T : class
{
T result;
if (!Parse(str, out result))
return null;
return result;
}
public static T? ParseOrNull<T>(this string value)
where T : struct
{
T result = default(T);
object[] parameters = new object[] { value, result };
foreach (System.Reflection.MethodInfo method in
typeof(T).GetMethods()
.Where(method => method.Name == "TryParse")
.Where(method => method.GetParameters().Length == 2) //as opposed to the 4 argument version
.Take(1) //shouldn't be needed, but just in case
)
{
method.Invoke(null, parameters);
}
return (T)parameters[1];
}
As Reed mentions, I'd rather not use an extension method of string. I'd just use Parser.Parse(string value). Easy fix though, just remove the 'this' and voila.
I want to do something like this but C# doesn't accept this:
public static void setPrice(Double? value)
{
if (value != null) {
this.TextBoxPrice.Text = Math.Round(value, 2).ToString();
} else {
this.TextBoxPrice.Text = "No Price";
}
}
So does it mean using nullable type Double? is completely useless in this use case ? What can I use then ?
Update: I made a mystypo I actually meant
public static void setPrice(Double? value)
so I corrected.
You're not currently using a nullable type - Double is a non-nullable value type, so can never be null. This is what you want:
public static void setPrice(Double? value)
{
if (value != null) {
this.TextBoxPrice.Text = Math.Round(value.Value, 2).ToString();
} else {
this.TextBoxPrice.Text = "No Price";
}
}
On the other hand, you should not be using a double to represent financial values. It's inappropriate as a binary floating point type. Use decimal (or decimal?) instead.
(Note that Double? is equivalent to Nullable<Double>.)
If you've come from a Java background, you may be expecting Double to be a reference "wrapper" type to start with - it's not. In C# double is simply an alias for System.Double; they're the same type.
Jon's answer is fine -- pay particular attention to the bit about decimal -- but I thought I'd add that you can "lift" methods to nullable using higher-order programming. For example:
public static Func<T?, T?> Lift<T>(Func<T, T> func) where T : struct
{
return (T? t)=>t.HasValue ? (T?)func(t.Value) : (T?)null;
}
public static Func<A?, R> LiftRef<A, R>(Func<A, R> func) where A : struct where R : class
{
return (A? a)=>a.HasValue ? func(a.Value) : null;
}
And now you can say:
Func<decimal, decimal> round2 = x=>Math.Round(x, 2);
Func<decimal?, decimal?> liftedRound2 = Lift(round2);
Func<decimal?, string> liftedToString = LiftRef(decimal.ToString);
...
public static void SetPrice(decimal? value)
{
this.TextBoxPrice.Text == liftedToString(liftedRound2(value)) ?? "No Price";
}
I agree with Jon Skeet's answer and just wanted to add that in that specific case you might consider simply adding a ClearPrice method - for reasons of clearer API + avoiding the if-else.
I have a method that uses an IList<T> as a parameter. I need to check what the type of that T object is and do something based on it. I was trying to use the T value, but the compiler does not not allow it. My solution is the following:
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
if (clause[0] is int || clause[0] is decimal)
{
//do something
}
else if (clause[0] is String)
{
//do something else
}
else if (...) //etc for all the types
else
{
throw new ApplicationException("Invalid type");
}
}
}
There has to be a better way to do this. Is there some way I can check the type of T that is passed in and then use a switch statement?
You could use overloads:
public static string BuildClause(List<string> l){...}
public static string BuildClause(List<int> l){...}
public static string BuildClause<T>(List<T> l){...}
Or you could inspect the type of the generic parameter:
Type listType = typeof(T);
if(listType == typeof(int)){...}
You can use typeof(T).
private static string BuildClause<T>(IList<T> clause)
{
Type itemType = typeof(T);
if(itemType == typeof(int) || itemType == typeof(decimal))
...
}
And, because C# has evolved, you can (now) use pattern matching.
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
switch (clause[0])
{
case int x: // do something with x, which is an int here...
case decimal x: // do something with x, which is a decimal here...
case string x: // do something with x, which is a string here...
...
default: throw new Exception("Invalid type");
}
}
}
And again with switch expressions in C# 8.0, the syntax gets even more succinct.
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
return clause[0] switch
{
int x => "some string related to this int",
decimal x => "some string related to this decimal",
string x => x,
...,
_ => throw new Exception("Invalid type")
}
}
}
I hope you find this helpful:
typeof(IList<T>).IsGenericType == true
typeof(IList<T>).GetGenericTypeDefinition() == typeof(IList<>)
typeof(IList<int>).GetGenericArguments()[0] == typeof(int)
https://dotnetfiddle.net/5qUZnt
By default know there is not a great way. Awhile back I got frustrated with this and wrote a little utility class that helped out a bit and made the syntax a bit cleaner. Essentially it turns the code into
TypeSwitcher.Do(clause[0],
TypeSwitch.Case<int>(x => ...), // x is an int
TypeSwitch.Case<decimal>(d => ...), // d is a decimal
TypeSwitch.Case<string>(s => ...)); // s is a string
Full blog post and details on the implementation are available here
http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx
The typeof operator...
typeof(T)
... won't work with the c# switch statement. But how about this? The following post contains a static class...
Is there a better alternative than this to 'switch on type'?
...that will let you write code like this:
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));
There is no way to use the switch statement for what you want it to do. The switch statement must be supplied with integral types, which does not include complex types such as a "Type" object, or any other object type for that matter.
For everyone that says checking types and doing something based on the type is not a great idea for generics I sort of agree but I think there could be some circumstances where this perfectly makes sense.
For example if you have a class that say is implemented like so (Note: I am not showing everything that this code does for simplicity and have simply cut and pasted into here so it may not build or work as intended like the entire code does but it gets the point across. Also, Unit is an enum):
public class FoodCount<TValue> : BaseFoodCount
{
public TValue Value { get; set; }
public override string ToString()
{
if (Value is decimal)
{
// Code not cleaned up yet
// Some code and values defined in base class
mstrValue = Value.ToString();
decimal mdecValue;
decimal.TryParse(mstrValue, out mdecValue);
mstrValue = decimal.Round(mdecValue).ToString();
mstrValue = mstrValue + mstrUnitOfMeasurement;
return mstrValue;
}
else
{
// Simply return a string
string str = Value.ToString() + mstrUnitOfMeasurement;
return str;
}
}
}
...
public class SaturatedFat : FoodCountWithDailyValue<decimal>
{
public SaturatedFat()
{
mUnit = Unit.g;
}
}
public class Fiber : FoodCount<int>
{
public Fiber()
{
mUnit = Unit.g;
}
}
public void DoSomething()
{
nutritionFields.SaturatedFat oSatFat = new nutritionFields.SaturatedFat();
string mstrValueToDisplayPreFormatted= oSatFat.ToString();
}
So in summary, I think there are valid reasons why you might want to check to see what type the generic is, in order to do something special.
Your construction completely defeats the purpose of a generic method. It's ugly on purpose because there must be a better way to achieve what you're trying to accomplish, although you haven't given us quite enough information to figure out what that is.
You can do typeOf(T), but I would double check your method and make sure your not violating single responsability here. This would be a code smell, and that's not to say it shouldn't be done but that you should be cautious.
The point of generics is being able to build type-agnostic algorthims were you don't care what the type is or as long as it fits within a certain set of criteria. Your implementation isn't very generic.
How about this :
// Checks to see if the value passed is valid.
if (!TypeDescriptor.GetConverter(typeof(T)).IsValid(value))
{
throw new ArgumentException();
}
My two cents:
In case you happen to have a generic method that returns a generic value but doesn't have generic parameters, you can use default(T) + (T)(object) cast, together with C# 8 pattern matching/type checks (as indicated in the other recent answers).
Example:
private static T Parse<T>(string str)
{
return default(T) switch
{
short => (T)(object)short.Parse(str),
ushort => (T)(object)ushort.Parse(str),
int => (T)(object)int.Parse(str),
uint => (T)(object)uint.Parse(str),
long => (T)(object)long.Parse(str),
ulong => (T)(object)ulong.Parse(str),
_ => throw new ArgumentException()
};
}
I have method that transforms some input value by the user passing it a Func delegate wich returns the new value (very over simplified for what I am trying to achieve)
public L Coerce<L>(string value, Func<string, L> coercer)
{
return coercer(value);
}
Coerce<int>("123", v => int.Parse(v));
This is fine however I also want to be able to write methods that override the behaviour for a specific type eg...
public int Coerce<int>(string value)
{
return Coerce<int>(value, v => int.Parse(v));
}
So basically calling
Coerce<int>("123"); // equivalent Coerce<int>("123", v => int.Parse(v));
will save me having to re-write the int.Parse for every Coerce. Of course this should then extend to handle
public decimal Coerce<decimal>(string value)
{
return Coerce<decimal>(value, v => int.Parse(v));
}
Etc etc.
Can this be done neatly?
James
Well, if you really don't want to do
Convert.ToInt32(value)
Then this will do what you are asking:
public T Coerce<T>(string value) where T : IConvertible
{
return (T)(((IConvertible)value).ToType(typeof(T),
CultureInfo.InvariantCulture));
}
Hence:
int x = Coerce<int>("123");
or
byte b = Coerce<byte>("123");
This will give you a compile-time error if you try to coerce to a non-convertible type, for example:
var x = Coerce<MyClass>("123"); //compile-time error
In which case you force the caller to use your Coerce(string value, Func<string,T> coercer) overload.
You could use a non-generic version:
public int CoerceInt32(string value)
{
return Coerce(value, int.Parse);
}
What is the purpose of this method?
Why do you want to write this:
int x = Coerce<int>("123", v => int.Parse(v));
instead of just this:
int x = int.Parse("123");
However, to answer your question, no, not "neatly". .Parse is a static method on the int and decimal types, and thus not available through your generic type.
The best you can hope for is to either write one overload per type you want to handle, or to write reflection code inside your method to figure out which static method to call.
And thus you get into a problem when you write this:
MyMagicType x = Coerce<MyMagicType>("123");
what then? Will you assume that MyMagicType has a .Parse method?
I'm afraid C# doesnt have template overriding like in C++. I came across a similar situation, and the way I had to work around it is to check the type at runtime:
public void DoStuff<T>(Dictionary<object, T> arg) {
// ....
if (typeof(T) == typeof(ClassA)) {
DoStuff((Dictionary<object, ClassA>)arg);
}
else (typeof(T) == typeof(ClassB)) {
DoStuff((Dictionary<object, ClassB>)arg);
}
else {
throw new ArgumentException("T must be ClassA or ClassB");
}
}