일반적인 TryParse
'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;
}
그것은 잘 작동하지만 예외를 그런 식으로 사용한다고 생각하지 않습니다.
업데이트 2 :
제네릭을 사용하지 않고 형식을 전달하도록 수정했습니다.
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
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);
}
}
최근에 일반적인 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);
흐름 제어에 try / catch를 사용하는 것은 끔찍한 정책입니다. 예외를 throw하면 런타임이 예외를 해결하는 동안 성능이 저하됩니다. 대신 변환하기 전에 데이터의 유효성을 검사하십시오.
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);
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});
}
이것은 각 제네릭 형식에 대해 정적 생성자를 사용하므로 지정된 형식에서 처음 호출 할 때 값 비싼 작업 만 수행하면됩니다. TryParse 메소드가있는 시스템 네임 스페이스의 모든 유형을 처리합니다. 열거 형을 제외하고 각 구조체 (구조체)의 nullable 버전에서도 작동합니다.
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;
}
}
이런 건 어때?
http://madskristensen.net/post/Universal-data-type-checker.aspx ( 아카이브 )
/// <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;
}
일반적인 유형에서는 할 수 없습니다.
당신이 할 수있는 일은 ITryParsable 인터페이스를 만들고이 인터페이스를 구현하는 사용자 정의 유형에 사용하는 것입니다.
나는 당신이 int
and과 같은 기본 유형으로 이것을 사용하려고한다고 생각합니다 DateTime
. 새 인터페이스를 구현하기 위해 이러한 유형을 변경할 수 없습니다.
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);
파티에 꽤 늦었지만 여기에 내가 생각해 낸 것이 있습니다. 예외는 없으며 한 번 (유형 당) 반성입니다.
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>()
다른 옵션이 있습니다.
여러 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);
}
}
내가 거의이 정확한 일을하고 싶을 때, 나는 그것을 반영하여 어려운 방법으로 구현해야했다. 주어진 T
, 또는를 찾은 후 호출 typeof(T)
하여 TryParse
또는 Parse
메소드를 찾아보십시오.
이것은 나의 시도이다. 나는 그것을 "운동"으로했다. 기존의 " Convert.ToX () "-ones 처럼 사용하기 위해 비슷하게 만들려고했지만 이것은 확장 방법입니다.
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; }
}
당신이 말했듯이, TryParse
인터페이스의 일부가 아닙니다. 또한 실제로 기본 static
이고 static
함수가 될 수 없으므로 주어진 기본 클래스의 멤버가 아닙니다 virtual
. 따라서 컴파일러에는 T
실제로이라는 멤버가 있는지 확인할 방법 TryParse
이 없으므로 작동하지 않습니다.
@Mark가 말했듯이 자체 인터페이스를 만들고 사용자 정의 유형을 사용할 수 있지만 내장 유형에 대해서는 운이 좋지 않습니다.
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);
}
}
이것은 '일반적인 제약'의 문제입니다. 특정 인터페이스가 없기 때문에 이전 답변의 제안을 따르지 않으면 멈춰 있습니다.
이에 대한 설명서는 다음 링크를 확인하십시오.
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
이러한 제약 조건을 사용하는 방법을 보여 주므로 더 많은 단서를 제공해야합니다.
http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx 에서 차용
이 참조를 따르는 경우 : 동적 유형으로 C # 4.0에서 정적 메소드를 호출하는 방법은 무엇입니까?
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;
}
나는 이런 식으로 작동하는 것을 얻었습니다.
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의 기사 에서 수정되었습니다 (AmbiguousMatchException 발생)
public static T Get<T>(string val)
{
return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromInvariantString(val);
}
와 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;
}
}
위의 정보를 사용하여 이것이 내가 개발 한 것입니다. 개체를 직접 변환 할 수 있습니다. 그렇지 않으면 개체를 문자열로 변환하고 원하는 개체 유형에 대해 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;
}
나는 여기에 많은 아이디어를 모았고 매우 짧은 해결책으로 끝났습니다.
이것은 문자열의 확장 방법입니다
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);
}
'' '
T.TryParse ... 왜?
나는 그러한 일반적인 TryParse
기능 을 갖는 데 아무런 이점이 없습니다 . 상충되는 동작으로 서로 다른 유형간에 데이터를 구문 분석하고 변환하기위한 전략이 너무 많습니다. 이 함수는 컨텍스트없는 방식으로 어떤 전략을 선택해야하는지 어떻게 알 수 있습니까?
- 전용 TryParse 함수가있는 클래스를 호출 할 수 있습니다.
- 전용 구문 분석 기능이있는 클래스는 try-catch 및 bool 결과로 래핑 될 수 있습니다.
- 연산자 오버로드가있는 클래스, 구문 분석을 어떻게 처리 할 수 있습니까?
- 형식 설명자는을 사용하여 기본 제공됩니다
Convert.ChangeType
. 이 API는 런타임에 사용자 정의 할 수 있습니다. 함수에 기본 동작이 필요합니까? 아니면 사용자 정의가 가능합니까? - 매핑 프레임 워크가 구문 분석을 시도하도록 허용해야합니까?
- 위의 충돌을 어떻게 처리 하시겠습니까?
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;
}
}
참고 URL : https://stackoverflow.com/questions/2961656/generic-tryparse
'IT story' 카테고리의 다른 글
JAR 파일을 실행하는 방법 (0) | 2020.05.14 |
---|---|
const std :: string &보다 std :: string_view가 얼마나 빠릅니까? (0) | 2020.05.14 |
원격 저장소에서 기록 커밋 (0) | 2020.05.14 |
Joda-Time : 기간, 간격 및 기간의 차이점은 무엇입니까? (0) | 2020.05.14 |
정적 클래스 멤버에 대한 정의되지 않은 참조 (0) | 2020.05.14 |