代码之家  ›  专栏  ›  技术社区  ›  TheSoftwareJedi jac

我如何解决这个问题以进行到Nullable<T>的泛型转换?

  •  45
  • TheSoftwareJedi jac  · 技术社区  · 17 年前

    我目前使用这个方便的转换扩展方法在类型之间进行转换:

        public static T To<T>(this IConvertible obj)
        {
            return (T)Convert.ChangeType(obj, typeof(T));
        }
    

    但是,它不喜欢将有效值转换为可空值,例如,此操作失败:

        "1".To<int?>();
    

    显然,1很容易转换为(int?),但它会得到错误:

        Invalid cast from 'System.String' to 'System.Nullable`1[[System.Int32, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]'.
    

    packageDb.Quantity = package.package.ElementDeep(Namespace + "PackageQuantity", Namespace + "ActualQuantity", Namespace + "Quantity").ValueOrNull().To<int?>();
    

    如果Convert.ChangeType不喜欢Nullable,有人有什么好主意吗?

    8 回复  |  直到 17 年前
        1
  •  99
  •   LukeH    11 年前
    public static T To<T>(this IConvertible obj)
    {
        Type t = typeof(T);
        Type u = Nullable.GetUnderlyingType(t);
    
        if (u != null)
        {
            return (obj == null) ? default(T) : (T)Convert.ChangeType(obj, u);
        }
        else
        {
            return (T)Convert.ChangeType(obj, t);
        }
    }
    
        2
  •  4
  •   Henrique    17 年前
    public static T To<T>(this IConvertible obj) 
    {
        Type t = typeof(T);
        if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
            t = t.GetGenericArguments()[0];
    
        return (T)Convert.ChangeType(obj, t); 
    }
    

    但是如果转换失败,它将抛出一个异常,而不是像预期的那样返回null。

        3
  •  3
  •   Nick Strupat    13 年前

    我最终得到了这个

    private static T To<T>(this Object @object, Boolean returnDefaultOnException)
    {
        Type type = typeof(T);
        Type underlyingTypeOfNullable = Nullable.GetUnderlyingType(type);
        try
        {
            return (T) Convert.ChangeType(@object, underlyingTypeOfNullable ?? type);
        }
        catch (Exception exception)
        {
            if (returnDefaultOnException)
                return default(T);
            String typeName = type.Name;
            if (underlyingTypeOfNullable != null)
                typeName += " of " + underlyingTypeOfNullable.Name;
            throw new InvalidCastException("Object can't be cast to " + typeName, exception);
    
        }
    }
    public static T To<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: false); }
    public static T ToOrDefault<T>(this Object @object) { return @object.To<T>(returnDefaultOnException: true); }
    

    Single SingleOrDefault First FirstOrDefault

    简言之 To<T>() ToOrDefault<T>() 尝试转换并返回 default(T) 一旦失败。

        4
  •  2
  •   Adam Robinson    17 年前

    (int?)1 ?

    public static T? ToNullable<T>(this T obj) where T:struct
    {
        return (T?)obj;
    }
    

    编辑

    在查看您的编辑之后,为什么我提供的通用函数不能替代您的编辑 To<T> 那行代码中的函数?对于任何类型,都不能允许转换为Nullable(这就是为什么 ChangeType 因为泛型只接受值类型。您要么使用我提供的函数,要么更改您的签名 仅接受值类型并为 Nullable<T> .

        5
  •  2
  •   Eugenio Miró    15 年前

        private static Type ResolveType(String typeName)
        {
            Type t = Type.GetType(typeName);
            if (t == null)
                return null;
    
            Type u = Nullable.GetUnderlyingType(t);
    
            if (u != null) {
                t = u;
            }
            return t;
        }
    

    因为我是从字符串开始的,而不是从类型开始的。。。 思想?

        6
  •  1
  •   Community Mohan Dere    9 年前

    这是我目前使用的方法(我得到了答案) SO

        public static Nullable<T> ConvertToNullable<T>(this string s) where T : struct
        {
            if (!string.IsNullOrEmpty(s.Trim()))
            {
                TypeConverter conv = TypeDescriptor.GetConverter(typeof(Nullable<>).MakeGenericType(typeof(T)));
                return (Nullable<T>)conv.ConvertFrom(s);
            }
            return null;
        }
    
        7
  •  0
  •   Hossein Shahabi    10 年前

    扩展@LukeH代码:

    public static T GetValue<T>(string Literal, T DefaultValue)
        {
            if (Literal == null || Literal == "" || Literal == string.Empty) return DefaultValue;
            IConvertible obj = Literal;
            Type t = typeof(T);
            Type u = Nullable.GetUnderlyingType(t);
    
            if (u != null)
            {
                return (obj == null) ? DefaultValue : (T)Convert.ChangeType(obj, u);
            }
            else
            {
                return (T)Convert.ChangeType(obj, t);
            }
        }
    
        8
  •  0
  •   Pangamma    8 年前

    这种方法可以满足您的需要,而且在执行时看起来很不错。

        /// <summary>
        /// <para>More convenient than using T.TryParse(string, out T). 
        /// Works with primitive types, structs, and enums.
        /// Tries to parse the string to an instance of the type specified.
        /// If the input cannot be parsed, null will be returned.
        /// </para>
        /// <para>
        /// If the value of the caller is null, null will be returned.
        /// So if you have "string s = null;" and then you try "s.ToNullable...",
        /// null will be returned. No null exception will be thrown. 
        /// </para>
        /// <author>Contributed by Taylor Love (Pangamma)</author>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="p_self"></param>
        /// <returns></returns>
        public static T? ToNullable<T>(this string p_self) where T : struct
        {
            if (!string.IsNullOrEmpty(p_self))
            {
                var converter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
                if (converter.IsValid(p_self)) return (T)converter.ConvertFromString(p_self);
                if (typeof(T).IsEnum) { T t; if (Enum.TryParse<T>(p_self, out t)) return t;}
            }
    
            return null;
        }
    

    https://github.com/Pangamma/PangammaUtilities-CSharp/tree/master/src/StringExtensions