Generic TryParse

C#GenericsTryparse

C# Problem Overview


I am trying to create a generic extension that uses 'TryParse' to check if a string is a given type:

public static bool Is<T>(this string input)
{
    T notUsed;
    return T.TryParse(input, out notUsed);
}

this won't compile as it cannot resolve symbol 'TryParse'

As I understand, 'TryParse' is not part of any interface.

Is this possible to do at all?

Update:

Using the answers below I have come up with:

public static bool Is<T>(this string input)
{
    try
    {
        TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
    }
    catch
    {
        return false;
    }

    return true;
}

It works quite well but I think using exceptions in that way doesn't feel right to me.

Update2:

Modified to pass type rather than use generics:

public static bool Is(this string input, Type targetType)
{
    try
    {
        TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
        return true;
    }
    catch
    {
        return false;
    }
}

C# Solutions


Solution 1 - C#

You should use the TypeDescriptor class:

public static T Convert<T>(this string input)
{
    try
    {
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if(converter != null)
        {
            // Cast ConvertFromString(string text) : object to (T)
            return (T)converter.ConvertFromString(input);
        }
        return default(T);
    }
    catch (NotSupportedException)
    {
        return default(T);
    }
}

Solution 2 - C#

I also required a generic TryParse recently. Here's what I came up with;

public static T? TryParse<T>(string value, TryParseHandler<T> handler) where T : struct
{
    if (String.IsNullOrEmpty(value))
        return null;
    T result;
    if (handler(value, out result))
        return result;
    Trace.TraceWarning("Invalid value '{0}'", value);
    return null;
}

public delegate bool TryParseHandler<T>(string value, out T result);

Then it's simply a matter of calling thusly:

var value = TryParse<int>("123", int.TryParse);
var value2 = TryParse<decimal>("123.123", decimal.TryParse);

Solution 3 - C#

Using try/catches for flow control is a terrible policy. Throw an exception causes performance lags while the runtime works around the exception. Instead validate the data before converting.

var attemptedValue = "asdfasdsd";
var type = typeof(int);
var converter = TypeDescriptor.GetConverter(type);
if (converter != null &&  converter.IsValid(attemptedValue))
    return converter.ConvertFromString(attemptedValue);
else
    return Activator.CreateInstance(type);

Solution 4 - C#

If you are set on using TryParse, you can use reflection and do it like this:

public static bool Is<T>(this string input)
{
    var type = typeof (T);
    var temp = default(T);
    var method = type.GetMethod(
        "TryParse",
        new[]
            {
                typeof (string),
                Type.GetType(string.Format("{0}&", type.FullName))
            });
    return (bool) method.Invoke(null, new object[] {input, temp});
}

Solution 5 - C#

How about something like this?

http://madskristensen.net/post/Universal-data-type-checker.aspx (Archive)

/// <summary> 
/// Checks the specified value to see if it can be 
/// converted into the specified type. 
/// <remarks> 
/// The method supports all the primitive types of the CLR 
/// such as int, boolean, double, guid etc. as well as other 
/// simple types like Color and Unit and custom enum types. 
/// </remarks> 
/// </summary> 
/// <param name="value">The value to check.</param> 
/// <param name="type">The type that the value will be checked against.</param> 
/// <returns>True if the value can convert to the given type, otherwise false. </returns> 
public static bool CanConvert(string value, Type type) 
{ 
    if (string.IsNullOrEmpty(value) || type == null) return false;
    System.ComponentModel.TypeConverter conv = System.ComponentModel.TypeDescriptor.GetConverter(type);
    if (conv.CanConvertFrom(typeof(string)))
    { 
        try 
        {
            conv.ConvertFrom(value); 
            return true;
        } 
        catch 
        {
        } 
     } 
     return false;
  }

This can be converted to a generic method pretty easily.

 public static bool Is<T>(this string value)
 {
    if (string.IsNullOrEmpty(value)) return false;
    var conv = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));

    if (conv.CanConvertFrom(typeof(string)))
    { 
        try 
        {
            conv.ConvertFrom(value); 
            return true;
        } 
        catch 
        {
        } 
     } 
     return false;
}

Solution 6 - C#

This uses a static constructor for each generic type, so it only has to do the expensive work the first time you call it on a given type. It handles all the types in the system namespace which have TryParse methods. It also works with nullable versions of each of those (that are structs) except for enumerations.

    public static bool TryParse<t>(this string Value, out t result)
    {
        return TryParser<t>.TryParse(Value.SafeTrim(), out result);
    }
    private delegate bool TryParseDelegate<t>(string value, out t result);
    private static class TryParser<T>
    {
        private static TryParseDelegate<T> parser;
        // Static constructor:
        static TryParser()
        {
            Type t = typeof(T);
            if (t.IsEnum)
                AssignClass<T>(GetEnumTryParse<T>());
            else if (t == typeof(bool) || t == typeof(bool?))
                AssignStruct<bool>(bool.TryParse);
            else if (t == typeof(byte) || t == typeof(byte?))
                AssignStruct<byte>(byte.TryParse);
            else if (t == typeof(short) || t == typeof(short?))
                AssignStruct<short>(short.TryParse);
            else if (t == typeof(char) || t == typeof(char?))
                AssignStruct<char>(char.TryParse);
            else if (t == typeof(int) || t == typeof(int?))
                AssignStruct<int>(int.TryParse);
            else if (t == typeof(long) || t == typeof(long?))
                AssignStruct<long>(long.TryParse);
            else if (t == typeof(sbyte) || t == typeof(sbyte?))
                AssignStruct<sbyte>(sbyte.TryParse);
            else if (t == typeof(ushort) || t == typeof(ushort?))
                AssignStruct<ushort>(ushort.TryParse);
            else if (t == typeof(uint) || t == typeof(uint?))
                AssignStruct<uint>(uint.TryParse);
            else if (t == typeof(ulong) || t == typeof(ulong?))
                AssignStruct<ulong>(ulong.TryParse);
            else if (t == typeof(decimal) || t == typeof(decimal?))
                AssignStruct<decimal>(decimal.TryParse);
            else if (t == typeof(float) || t == typeof(float?))
                AssignStruct<float>(float.TryParse);
            else if (t == typeof(double) || t == typeof(double?))
                AssignStruct<double>(double.TryParse);
            else if (t == typeof(DateTime) || t == typeof(DateTime?))
                AssignStruct<DateTime>(DateTime.TryParse);
            else if (t == typeof(TimeSpan) || t == typeof(TimeSpan?))
                AssignStruct<TimeSpan>(TimeSpan.TryParse);
            else if (t == typeof(Guid) || t == typeof(Guid?))
                AssignStruct<Guid>(Guid.TryParse);
            else if (t == typeof(Version))
                AssignClass<Version>(Version.TryParse);
        }
        private static void AssignStruct<t>(TryParseDelegate<t> del)
            where t: struct
        {
            TryParser<t>.parser = del;
            if (typeof(t).IsGenericType
                && typeof(t).GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                return;
            }
            AssignClass<t?>(TryParseNullable<t>);
        }
        private static void AssignClass<t>(TryParseDelegate<t> del)
        {
            TryParser<t>.parser = del;
        }
        public static bool TryParse(string Value, out T Result)
        {
            if (parser == null)
            {
                Result = default(T);
                return false;
            }
            return parser(Value, out Result);
        }
    }

    private static bool TryParseEnum<t>(this string Value, out t result)
    {
        try
        {
            object temp = Enum.Parse(typeof(t), Value, true);
            if (temp is t)
            {
                result = (t)temp;
                return true;
            }
        }
        catch
        {
        }
        result = default(t);
        return false;
    }
    private static MethodInfo EnumTryParseMethod;
    private static TryParseDelegate<t> GetEnumTryParse<t>()
    {
        Type type = typeof(t);

        if (EnumTryParseMethod == null)
        {
            var methods = typeof(Enum).GetMethods(
                BindingFlags.Public | BindingFlags.Static);
            foreach (var method in methods)
                if (method.Name == "TryParse"
                    && method.IsGenericMethodDefinition
                    && method.GetParameters().Length == 2
                    && method.GetParameters()[0].ParameterType == typeof(string))
                {
                    EnumTryParseMethod = method;
                    break;
                }
        }
        var result = Delegate.CreateDelegate(
            typeof(TryParseDelegate<t>),
            EnumTryParseMethod.MakeGenericMethod(type), false)
            as TryParseDelegate<t>;
        if (result == null)
            return TryParseEnum<t>;
        else
            return result;
    }

    private static bool TryParseNullable<t>(string Value, out t? Result)
        where t: struct
    {
        t temp;
        if (TryParser<t>.TryParse(Value, out temp))
        {
            Result = temp;
            return true;
        }
        else
        {
            Result = null;
            return false;
        }
    }

Solution 7 - C#

You can't do it on general types.

What you could do is to create an interface ITryParsable and use it for custom types that implement this interface.

I guess though that you intend to use this with basic types like int and DateTime. You can't change these types to implement new interfaces.

Solution 8 - C#

Quite a bit late to the party, but here's what I came up with. No exceptions, one-time (per type) reflection.

public static class Extensions {
    public static T? ParseAs<T>(this string str) where T : struct {
        T val;
        return GenericHelper<T>.TryParse(str, out val) ? val : default(T?);
    }
    public static T ParseAs<T>(this string str, T defaultVal) {
        T val;
        return GenericHelper<T>.TryParse(str, out val) ? val : defaultVal;
    }

    private static class GenericHelper<T> {
        public delegate bool TryParseFunc(string str, out T result);

        private static TryParseFunc tryParse;
        public static TryParseFunc TryParse {
            get {
                if (tryParse == null)
                    tryParse = Delegate.CreateDelegate(
                        typeof(TryParseFunc), typeof(T), "TryParse") as TryParseFunc;
                return tryParse;
            }
        }
    }
}

The extra class is required because extention methods are not permitted inside generic classes. This allows simple usage, as shown below, and only hits reflection the first time a type is used.

"5643".ParseAs<int>()

Solution 9 - C#

Inspired by the solution posted here by Charlie Brown, I created a generic TryParse using reflection that optionally outputs the parsed value:

/// <summary>
/// Tries to convert the specified string representation of a logical value to
/// its type T equivalent. A return value indicates whether the conversion
/// succeeded or failed.
/// </summary>
/// <typeparam name="T">The type to try and convert to.</typeparam>
/// <param name="value">A string containing the value to try and convert.</param>
/// <param name="result">If the conversion was successful, the converted value of type T.</param>
/// <returns>If value was converted successfully, true; otherwise false.</returns>
public static bool TryParse<T>(string value, out T result) where T : struct {
    var tryParseMethod = typeof(T).GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, null, new [] { typeof(string), typeof(T).MakeByRefType() }, null);
    var parameters = new object[] { value, null };

    var retVal = (bool)tryParseMethod.Invoke(null, parameters);

    result = (T)parameters[1];
    return retVal;
}

/// <summary>
/// Tries to convert the specified string representation of a logical value to
/// its type T equivalent. A return value indicates whether the conversion
/// succeeded or failed.
/// </summary>
/// <typeparam name="T">The type to try and convert to.</typeparam>
/// <param name="value">A string containing the value to try and convert.</param>
/// <returns>If value was converted successfully, true; otherwise false.</returns>
public static bool TryParse<T>(string value) where T : struct {
    T throwaway;
    var retVal = TryParse(value, out throwaway);
    return retVal;
}

It can be called thus:

string input = "123";
decimal myDecimal;

bool myIntSuccess = TryParse<int>(input);
bool myDecimalSuccess = TryParse<decimal>(input, out myDecimal);

Update:
Also thanks to YotaXP's solution which I really like, I created a version that doesn't use extension methods but still has a singleton, minimizing the need to do reflection:

/// <summary>
/// Provides some extra parsing functionality for value types.
/// </summary>
/// <typeparam name="T">The value type T to operate on.</typeparam>
public static class TryParseHelper<T> where T : struct {
    private delegate bool TryParseFunc(string str, out T result);

    private static TryParseFunc tryParseFuncCached;

    private static TryParseFunc tryParseCached {
        get {
            return tryParseFuncCached ?? (tryParseFuncCached = Delegate.CreateDelegate(typeof(TryParseFunc), typeof(T), "TryParse") as TryParseFunc);
        }
    }

    /// <summary>
    /// Tries to convert the specified string representation of a logical value to
    /// its type T equivalent. A return value indicates whether the conversion
    /// succeeded or failed.
    /// </summary>
    /// <param name="value">A string containing the value to try and convert.</param>
    /// <param name="result">If the conversion was successful, the converted value of type T.</param>
    /// <returns>If value was converted successfully, true; otherwise false.</returns>
    public static bool TryParse(string value, out T result) {
        return tryParseCached(value, out result);
    }

    /// <summary>
    /// Tries to convert the specified string representation of a logical value to
    /// its type T equivalent. A return value indicates whether the conversion
    /// succeeded or failed.
    /// </summary>
    /// <param name="value">A string containing the value to try and convert.</param>
    /// <returns>If value was converted successfully, true; otherwise false.</returns>
    public static bool TryParse(string value) {
        T throwaway;
        return TryParse(value, out throwaway);
    }
}

Call it like this:

string input = "987";
decimal myDecimal;

bool myIntSuccess = TryParseHelper<int>.TryParse(input);
bool myDecimalSuccess = TryParseHelper<decimal>.TryParse(input, out myDecimal);

Solution 10 - C#

Here's another option.

I wrote a class that makes it easy to register any number of TryParse handlers. It lets me do this:

var tp = new TryParser();

tp.Register<int>(int.TryParse);
tp.Register<decimal>(decimal.TryParse);
tp.Register<double>(double.TryParse);

int x;
if (tp.TryParse("42", out x))
{
	Console.WriteLine(x);
};

I get 42 printed to the console.

The class is:

public class TryParser
{
	public delegate bool TryParseDelegate<T>(string s, out T result);

	private Dictionary<Type, Delegate> _tryParsers = new Dictionary<Type, Delegate>();

	public void Register<T>(TryParseDelegate<T> d)
	{
		_tryParsers[typeof(T)] = d;
	}

	public bool Deregister<T>()
	{
		return _tryParsers.Remove(typeof(T));
	}

	public bool TryParse<T>(string s, out T result)
	{
		if (!_tryParsers.ContainsKey(typeof(T)))
		{
			throw new ArgumentException("Does not contain parser for " + typeof(T).FullName + ".");
		}
		var d = (TryParseDelegate<T>)_tryParsers[typeof(T)];
		return d(s, out result);
	}
}

Solution 11 - C#

When I wanted to do almost this exact thing, I had to implement it the hard way, given reflection. Given T, reflect on typeof(T) and look for a TryParse or Parse method, invoking it if you've found it.

Solution 12 - C#

This is my try. I did it as an "exercise". I tried to make it as similar to use as the existing "Convert.ToX()"-ones etc. But this one is extension method:

    public static bool TryParse<T>(this String str, out T parsedValue)
    {
        try
        {
            parsedValue = (T)Convert.ChangeType(str, typeof(T));
            return true;
        }

        catch { parsedValue = default(T); return false; }
    }

Solution 13 - C#

As you said, TryParse is not part of an interface. It is also not a member of any given base class since it's actually static and static functions can't be virtual. So, the compiler has no way of assuring that T actually has a member called TryParse, so this doesn't work.

As @Mark said, you could create your own interface and use custom types, but you're out of luck for the built-in types.

Solution 14 - C#

public static class Primitive
{
    public static DateTime? TryParseExact(string text, string format, IFormatProvider formatProvider = null, DateTimeStyles? style = null)
    {
        DateTime result;
        if (DateTime.TryParseExact(text, format, formatProvider, style ?? DateTimeStyles.None, out result))
            return result;
        return null;
    }

    public static TResult? TryParse<TResult>(string text) where TResult : struct
    {
        TResult result;
        if (Delegates<TResult>.TryParse(text, out result))
            return result;
        return null;
    }

    public static bool TryParse<TResult>(string text, out TResult result) => Delegates<TResult>.TryParse(text, out result);

    public static class Delegates<TResult>
    {
        private delegate bool TryParseDelegate(string text, out TResult result);

        private static readonly TryParseDelegate _parser = (TryParseDelegate)Delegate.CreateDelegate(typeof(TryParseDelegate), typeof(TResult), "TryParse");

        public static bool TryParse(string text, out TResult result) => _parser(text, out result);
    }
}

Solution 15 - C#

This is a question of 'generic constraints'. Because you don't have a specific interface then you are stuck unless you follow the suggestions of the previous answer.

For documentation on this, check the following link:

http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx

It shows you how to use these constraints and should give you some more clues.

Solution 16 - C#

Borrowed from http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx

when following this reference: https://stackoverflow.com/questions/2825355/how-to-invoke-static-method-in-c4-0-with-dynamic-type

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Reflection;

namespace Utils
{
   public class StaticMembersDynamicWrapper : DynamicObject
   {
      private Type _type;

      public StaticMembersDynamicWrapper(Type type) { _type = type; }

      // Handle static methods
      public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
      {
         var methods = _type
            .GetMethods(BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public)
            .Where(methodInfo => methodInfo.Name == binder.Name);
         
         var method = methods.FirstOrDefault();
         if (method != null)
         {
            result = method.Invoke(null, args);
            return true;
         }

         result = null;
         return false;
      }
   }

   public static class StaticMembersDynamicWrapperExtensions
   {
      static Dictionary<Type, DynamicObject> cache =
         new Dictionary<Type, DynamicObject>
         {
            {typeof(double), new StaticMembersDynamicWrapper(typeof(double))},
            {typeof(float), new StaticMembersDynamicWrapper(typeof(float))},
            {typeof(uint), new StaticMembersDynamicWrapper(typeof(uint))},
            {typeof(int), new StaticMembersDynamicWrapper(typeof(int))},
            {typeof(sbyte), new StaticMembersDynamicWrapper(typeof(sbyte))}
         };

      /// <summary>
      /// Allows access to static fields, properties, and methods, resolved at run-time.
      /// </summary>
      public static dynamic StaticMembers(this Type type)
      {
         DynamicObject retVal;
         if (!cache.TryGetValue(type, out retVal))
            return new StaticMembersDynamicWrapper(type);

         return retVal;
      }
   }
}

And use it as follows:

  public static T? ParseNumeric<T>(this string str, bool throws = true)
     where T : struct
  {
     var statics = typeof(T).StaticMembers();
     
     if (throws) return statics.Parse(str);

     T retval;
     if (!statics.TryParse(str, out retval)) return null;

     return retval;
  }

Solution 17 - C#

I managed to get something that works like this

    var result = "44".TryParse<int>();

    Console.WriteLine( "type={0}, value={1}, valid={2}",        
    result.Value.GetType(), result.Value, result.IsValid );

Here's my code

 public static class TryParseGeneric
    {
        //extend int
        public static dynamic TryParse<T>( this string input )
        {    
            dynamic runner = new StaticMembersDynamicWrapper( typeof( T ) );

            T value;
            bool isValid = runner.TryParse( input, out value );
            return new { IsValid = isValid, Value = value };
        }
    }


    public class StaticMembersDynamicWrapper : DynamicObject
    {
        private readonly Type _type;
        public StaticMembersDynamicWrapper( Type type ) { _type = type; }

        // Handle static properties
        public override bool TryGetMember( GetMemberBinder binder, out object result )
        {
            PropertyInfo prop = _type.GetProperty( binder.Name, BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public );
            if ( prop == null )
            {
                result = null;
                return false;
            }

            result = prop.GetValue( null, null );
            return true;
        }

        // Handle static methods
        public override bool TryInvokeMember( InvokeMemberBinder binder, object [] args, out object result )
        {
            var methods = _type
            .GetMethods( BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Public ).Where( methodInfo => methodInfo.Name == binder.Name );

            var method = methods.FirstOrDefault();

            if ( method == null )
            {
                result = null;

                return false;
            }

            result = method.Invoke( null, args );

            return true;
        }
    }

The StaticMembersDynamicWrapper is adapted from David Ebbo's article (it was throwing an AmbiguousMatchException)

Solution 18 - C#

public static T Get<T>(string val)
{ 
    return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromInvariantString(val);
}

Solution 19 - C#

With TypeDescriptor class usage in TryParse related manner:

public static bool TryParse<T>(this string input, out T parsedValue)
{
	parsedValue = default(T);
	try
	{
		var converter = TypeDescriptor.GetConverter(typeof(T));
		parsedValue = (T)converter.ConvertFromString(input);
		return true;
	}
	catch (NotSupportedException)
	{
		return false;
	}
}

Solution 20 - C#

Using the information above, this is what I developed. It will convert the object directly is possible, otherwise it will convert the object to a string and call the TryParse method for the desired object type.

I cache the methods in a dictionary as each is encountered to reduce the method fetching load.

It's possible to test if the object can be directly converted to the target type, which would further reduce the string conversion part. But I'll leave that out for now.

    /// <summary>
    /// Used to store TryParse converter methods
    /// </summary>
    private static readonly Dictionary<Type, MethodInfo> TypeConverters = new Dictionary<Type, MethodInfo>();

    /// <summary>
    /// Attempt to parse the input object to the output type
    /// </summary>
    /// <typeparam name="T">output type</typeparam>
    /// <param name="obj">input object</param>
    /// <param name="result">output result on success, default(T) on failure</param>
    /// <returns>Success</returns>
    public static bool TryParse<T>([CanBeNull] object obj, out T result)
    {
        result = default(T);

        try
        {
            switch (obj)
            {
                // don't waste time on null objects
                case null: return false;
                
                // if the object is already of type T, just return the value
                case T val:
                    result = val;
                    return true;
            }

            // convert the object into type T via string conversion
            var input = ((obj as string) ?? obj.ToString()).Trim();
            if (string.IsNullOrEmpty(input)) return false;

            var type = typeof (T);
            Debug.WriteLine($"Info: {nameof(TryParse)}<{type.Name}>({obj.GetType().Name}=\"{input}\")");

            if (! TypeConverters.TryGetValue(type, out var method))
            {
                // get the TryParse method for this type
                method = type.GetMethod("TryParse",
                    new[]
                    {
                        typeof (string),
                        Type.GetType($"{type.FullName}&")
                    });

                if (method is null)
                    Debug.WriteLine($"FAILED: Cannot get method for {type.Name}.TryParse()");

                // store it so we don't have to do this again
                TypeConverters.Add(type, method);
            }

            // have to keep a reference to parameters if you want to get the returned ref value
            var parameters = new object[] {input, null};
            if ((bool?) method?.Invoke(null, parameters) == true)
            {
                result = (T) parameters[1];
                return true;
            }                
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
        }

        return false;
    }

Solution 21 - C#

I put a bunch of ideas here together and ended up with a very short solution.

This is an extension method on a string

enter code here

I made it with the same foot print as the TryParse methods on the numeric types

    /// <summary>
    /// string.TryParse()
    /// 
    /// This generic extension method will take a string
    ///     make sure it is not null or empty
    ///     make sure it represents some type of number e.g. "123" not "abc"
    ///     It then calls the appropriate converter for the type of T
    /// </summary>
    /// <typeparam name="T">The type of the desired retrunValue e.g. int, float, byte, decimal...</typeparam>
    /// <param name="targetText">The text to be converted</param>
    /// <param name="returnValue">a populated value of the type T or the default(T) value which is likely to be 0</param>
    /// <returns>true if the string was successfully parsed and converted otherwise false</returns>
    /// <example>
    /// float testValue = 0;
    ///  if ( "1234".TryParse<float>( out testValue ) )
    ///  {
    ///      doSomethingGood();
    ///  }
    ///  else
    ///  {
    ///      handleTheBadness();
    ///  }
    /// </example>
    public static bool TryParse<T>(this string targetText, out T returnValue )
    {
        bool returnStatus = false;

        returnValue = default(T);

        //
        // make sure the string is not null or empty and likely a number...
        // call whatever you like here or just leave it out - I would
        // at least make sure the string was not null or empty  
        //
        if ( ValidatedInputAnyWayYouLike(targetText) )
        {

            //
            // try to catch anything that blows up in the conversion process...
            //
            try
            {
                var type = typeof(T);
                var converter = TypeDescriptor.GetConverter(type);

                if (converter != null && converter.IsValid(targetText))
                {
                    returnValue = (T)converter.ConvertFromString(targetText);
                    returnStatus = true;
                }

            }
            catch
            {
                // just swallow the exception and return the default values for failure
            }

        }

        return (returnStatus);

    }

'''

Solution 22 - C#

T.TryParse ... why?

I see no benefit in having such generic TryParse function. There are too many different strategies for parsing and converting data between different types, with possible conflicting behavior. How could this function know which strategy to pick in a context-free fashion?

  • classes with dedicated TryParse functions could be called
  • classes with dedicated Parse functions could be wrapped with try-catch and bool result
  • classes with operator overloads, how would you let them handle the parsing?
  • type descriptors are built-in using Convert.ChangeType. This API is customisable at runtime. Does your function require default behavior or allow for customization?
  • should you allow any mapping framework to try to parse for you?
  • how would you handle conflicts in the above?

Solution 23 - C#

A version for getting descendants from XDocument.

public static T Get<T>(XDocument xml, string descendant, T @default)
{
    try
    {
        var converter = TypeDescriptor.GetConverter(typeof (T));
        if (converter != null)
        {
            return (T) converter.ConvertFromString(xml.Descendants(descendant).Single().Value);
        }
        return @default;
    }
    catch
    {
        return @default;
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPiers MyersView Question on Stackoverflow
Solution 1 - C#lukeView Answer on Stackoverflow
Solution 2 - C#Charlie BrownView Answer on Stackoverflow
Solution 3 - C#Thinking SitesView Answer on Stackoverflow
Solution 4 - C#Joseph SturtevantView Answer on Stackoverflow
Solution 5 - C#BobView Answer on Stackoverflow
Solution 6 - C#Bryce WagnerView Answer on Stackoverflow
Solution 7 - C#Mark ByersView Answer on Stackoverflow
Solution 8 - C#YotaXPView Answer on Stackoverflow
Solution 9 - C#JezView Answer on Stackoverflow
Solution 10 - C#EnigmativityView Answer on Stackoverflow
Solution 11 - C#JSBÕ±Õ¸Õ£Õ¹View Answer on Stackoverflow
Solution 12 - C#W0lfw00dsView Answer on Stackoverflow
Solution 13 - C#DonnieView Answer on Stackoverflow
Solution 14 - C#ChaosPandionView Answer on Stackoverflow
Solution 15 - C#SimonView Answer on Stackoverflow
Solution 16 - C#GregCView Answer on Stackoverflow
Solution 17 - C#user372132View Answer on Stackoverflow
Solution 18 - C#mico.baracView Answer on Stackoverflow
Solution 19 - C#VolodymyrView Answer on Stackoverflow
Solution 20 - C#B DuffyView Answer on Stackoverflow
Solution 21 - C#JD HicksView Answer on Stackoverflow
Solution 22 - C#user11523568View Answer on Stackoverflow
Solution 23 - C#AndreasView Answer on Stackoverflow