我正在尝试创建一个使用'TryParse'检查字符串是否为给定类型的通用扩展:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
这将无法编译,因为它无法解析符号'TryParse'
据我了解,'TryParse'不是任何界面的一部分。
这可以吗?
更新
使用下面的答案,我想出了:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
它运作良好,但我认为以这种方式使用异常对我来说感觉不对。
UPDATE2:
修改为传递类型而不是使用泛型:
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
答案 0 :(得分:167)
您应该使用TypeDescriptor类:
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);
}
}
答案 1 :(得分:72)
我最近还需要一个通用的TryParse。这是我想出来的;
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);
然后,这只是一个如此称呼的问题:
var value = TryParse<int>("123", int.TryParse);
var value2 = TryParse<decimal>("123.123", decimal.TryParse);
答案 2 :(得分:29)
使用try / catches进行流量控制是一项糟糕的策略。抛出异常会导致性能滞后,而运行时则会遇到异常。而是在转换之前验证数据。
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);
答案 3 :(得分:14)
如果你开始使用TryParse,你可以使用反射并按照这样做:
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});
}
答案 4 :(得分:7)
这为每个泛型类型使用静态构造函数,因此它只需要在第一次在给定类型上调用它时执行昂贵的工作。它处理具有TryParse方法的系统命名空间中的所有类型。除了枚举之外,它还可以使用每个(可以是结构)的可空版本。
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;
}
}
答案 5 :(得分:4)
你不能在一般类型上这样做。
您可以做的是创建一个ITryParsable接口,并将其用于实现此接口的自定义类型。
我想你打算在int
和DateTime
等基本类型中使用它。您无法更改这些类型以实现新接口。
答案 6 :(得分:4)
受Charlie Brown在此处发布的解决方案的启发,我使用反射创建了一个通用的TryParse,可选择输出解析后的值:
/// <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;
}
可以这样称呼:
string input = "123";
decimal myDecimal;
bool myIntSuccess = TryParse<int>(input);
bool myDecimalSuccess = TryParse<decimal>(input, out myDecimal);
<强>更新强>
还要感谢我非常喜欢的YotaXP解决方案,我创建了一个不使用扩展方法但仍然有单例的版本,最大限度地减少了反射的需要:
/// <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);
}
}
这样称呼:
string input = "987";
decimal myDecimal;
bool myIntSuccess = TryParseHelper<int>.TryParse(input);
bool myDecimalSuccess = TryParseHelper<decimal>.TryParse(input, out myDecimal);
答案 7 :(得分:4)
这样的事情怎么样?
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;
}
这可以很容易地转换为通用方法。
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;
}
答案 8 :(得分:3)
这是另一种选择。
我编写了一个类,可以轻松注册任意数量的TryParse
个处理程序。它让我这样做:
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);
};
我将42
打印到控制台。
课程是:
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);
}
}
答案 9 :(得分:3)
参加聚会有点晚了,但这就是我想出来的。没有例外,一次性(每种类型)反映。
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;
}
}
}
}
额外的类是必需的,因为泛型类中不允许使用扩展方法。这允许简单使用,如下所示,并且仅在第一次使用类型时才会出现反射。
"5643".ParseAs<int>()
答案 10 :(得分:2)
这是我的尝试。我做了#34;练习&#34;。我尝试使其与现有的&#34; Convert.ToX()&#34; -one等类似。但这个是扩展方法:
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; }
}
答案 11 :(得分:2)
当我想做几乎这件事时,我必须以艰难的方式实施它,给予反思。给定T
,反映typeof(T)
并查找TryParse
或Parse
方法,如果找到则调用它。
答案 12 :(得分:1)
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);
}
}
答案 13 :(得分:1)
正如您所说,TryParse
不是界面的一部分。它也不是任何给定基类的成员,因为它实际上static
和static
函数不能是virtual
。因此,编译器无法确保T
实际上有一个名为TryParse
的成员,因此这不起作用。
正如@Mark所说,你可以创建自己的界面并使用自定义类型,但是对于内置类型你运气不好。
答案 14 :(得分:0)
使用上面的信息,这是我开发的。可以直接转换对象,否则将对象转换为字符串,然后为所需的对象类型调用TryParse方法。
我将方法缓存在字典中,以减少遇到的方法。
可以测试对象是否可以直接转换为目标类型,这将进一步减少字符串转换部分。但是,我暂时将其保留。
/// <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;
}
答案 15 :(得分:0)
我在这里提出了很多想法,最后得到了一个很短的解决方案。
这是字符串的扩展方法
enter code here
在数字类型上,它与TryParse方法具有相同的外观
/// <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);
}
'''
答案 16 :(得分:0)
与TypeDescriptor
相关的TryParse
类用法:
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;
}
}
答案 17 :(得分:0)
我认为拥有这样的通用TryParse
功能没有任何好处。解析和转换不同类型之间的数据的策略过多,可能会产生冲突的行为。此功能如何知道以上下文无关的方式选择哪种策略?
Convert.ChangeType
内置的。该API可在运行时自定义。您的功能是否需要默认行为或允许自定义?答案 18 :(得分:0)
public static T Get<T>(string val)
{
return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromInvariantString(val);
}
答案 19 :(得分:0)
我设法得到了像这样的东西
var result = "44".TryParse<int>();
Console.WriteLine( "type={0}, value={1}, valid={2}",
result.Value.GetType(), result.Value, result.IsValid );
这是我的代码
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;
}
}
StaticMembersDynamicWrapper改编自David Ebbo的article(它抛出了一个AmbiguousMatchException)
答案 20 :(得分:0)
借鉴http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx
遵循此引用时:How to invoke static method in C#4.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;
}
}
}
使用如下:
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;
}
答案 21 :(得分:0)
这是“通用约束”的问题。因为您没有特定的界面,所以除非您遵循上一个答案的建议,否则您将陷入困境。
有关此问题的文档,请查看以下链接:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
它向您展示了如何使用这些约束,并且应该为您提供更多线索。
答案 22 :(得分:-1)
从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;
}
}