如何在通用版本的TryParse()中转换为特定类型?

vdh*_*ant 19 .net c# generics casting

我有以下场景,我想传入字符串和泛型类型:

public class Worker {
    public void DoSomeWork<T>(string value) 
        where T : struct, IComparable<T>, IEquatable<T> { ... }
}
Run Code Online (Sandbox Code Playgroud)

在某些方面我需要将字符串值转换为其T值.但我不想做直接转换,因为如果字符串无法转换为类型,我需要执行一些逻辑T.

我在想我可以尝试使用,Convert.ChangeType()但这有一个问题,如果它不转换它将抛出异常,我将DoSomeWork()经常运行该方法,不必依赖try/catch来确定转换是否是有效.

因此,这让我思考,我知道,我将与数字类型来工作,因此T将是下列任何一项:int,uint,short,ushort,long,ulong,byte,sbyte,decimal,float,double.知道这一点我认为有可能提出一个更快的解决方案,我知道我将使用数字类型(注意,如果T不是数字类型,我抛出异常)......

public class NumericWorker {
    public void DoSomeWork<T>(string value) 
        where T : struct, IComparable<T>, IEquatable<T> 
    { 
        ParseDelegate<T> tryConverter = 
           SafeConvert.RetreiveNumericTryParseDelegate<T>();
        ... 
    }
}


public class SafeConvert
{
    public delegate bool ParseDelegate<T>(string value, out T result);

    public static ParseDelegate<T> RetreiveNumericTryParseDelegate<T>()
        where T : struct, IComparable<T>, IEquatable<T>
    {
        ParseDelegate<T> tryParseDelegate = null;

        if (typeof(T) == typeof(int))
        {
           tryParseDelegate = (string v, out T t) =>
              {
                 int typedValue; 
                 bool result = int.TryParse(v, out typedValue);
                 t = result ? (T)typedValue : default(T); 
                 //(T)Convert.ChangeType(typedValue, typeof(T)) : default(T);
                 return result;
              }; 
        }
        else if (typeof(T) == typeof(uint)) { ... }
        else if (typeof(T) == typeof(short)) { ... }
        else if (typeof(T) == typeof(ushort)) { ... }
        else if (typeof(T) == typeof(long)) { ... }
        else if (typeof(T) == typeof(ulong)) { ... }
        else if (typeof(T) == typeof(byte)) { ... }
        else if (typeof(T) == typeof(sbyte)) { ... }
        else if (typeof(T) == typeof(decimal)) { ... }
        else if (typeof(T) == typeof(float)) { ... }
        else if (typeof(T) == typeof(double)) { ... }

        return tryParseDelegate;
    }
}
Run Code Online (Sandbox Code Playgroud)

但上述有,我不能写的问题t = result ? (T)typedValue : default(T);作为铸造typedValueT原因的问题,我已经能够通过编写绕过它迄今是唯一的出路(T)Convert.ChangeType(typedValue, typeof(T)).但如果我这样做,我只是做另一个转换.

因此,我想知道是否有人知道我如何解决这个问题(如果你认为这ChangeType()是一个问题)或者如果有一个更好的解决方案我没有考虑过.

Sho*_*og9 40

t =结果?(T)typedValue:默认(T);

尝试:

t = result ? (T)(object)typedValue : default(T);
Run Code Online (Sandbox Code Playgroud)

是的,仿制药有时会有点烦人.

FWIW,我用一个更简单的包装周围Convert.ChangeType(),只是做了预检查空字符串.除非您将此用于未经检查的用户输入,否则这可能就足够了.


Ree*_*sey 12

鉴于这种:

因此T将是以下任何一种:int,uint,short,ushort,long,ulong,byte,sbyte,decimal,float,double.

我建议只使用Convert.ChangeType,而不用担心它.只有当你的字符串格式错误时才会出现异常,在这种情况下,你可以返回默认值(T).

即:

try
{
    result = Convert.ChangeType(value, typeof(T));
}
catch
{
    result = default(T);
}
Run Code Online (Sandbox Code Playgroud)


Sta*_* R. 5

ToType是这里的通用参数.这适用于可空类型,以防万一你需要它.您可以将主要方法提取为通用转换器,它将转换为任何类型,包括nullables.

    ToType result = default(ToType);    

    result = ChangeType<ToType>(typedValue);


  private T ChangeType<T>(object o)
{
   Type conversionType = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
   return (T)Convert.ChangeType(o, conversionType);
}
Run Code Online (Sandbox Code Playgroud)