字符串的通用类型转换


234

我有一个要用于存储另一个类的“属性”的类。这些属性仅具有名称和值。理想情况下,我希望能够添加类型化的属性,以便返回的“值”始终是我想要的类型。

该类型应始终为原始类型。此类继承了一个抽象类,该抽象类基本上将名称和值存储为字符串。这个子类将为基类增加一些类型安全性(并为我节省一些转换)。

因此,我创建了一个(大致)这样的类:

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

所以问题是:

是否有“通用”方式将字符串转换回原始类型?

我似乎找不到任何通用的接口来转换转换(像ITryParsable这样的东西会是理想的!)。


我希望看到您的具体课程示例,甚至只是片段。:)
乔恩·林贾普

您可以张贴基类的相关部分吗?
JJS 2012年

我想知道是否有人可以在.Net Standard 1.2中获得答案:/
Dan Rayson,

Answers:


374

我不确定我是否正确理解了您的意图,但是让我们看看这是否有帮助。

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}

我一直想知道如何将流反序列化为通用类型。谢谢:)
陷阱

3
我同意,尽管Convert.ChangeType这不是一个通用且可扩展的解决方案,但它适用于大多数基本类型。如果需要更好的方法,则可以将此方法包装到Tim所建议的更大的方法中,或者完全使用其他转换方法。
lubos hasko 2010年

18
我肯定会添加T:IConvertible的位置
MikeT

5
类型T不应为IConvertible,但base.Value的类型应为IConvertible。
chapluck 2015年

74

lubos hasko的方法无法为可为空。以下方法适用于可为null的对象。不过,我没有提出。我通过Google找到了它:http : //web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx归功于“金枪鱼Toksoz”

用法优先:

TConverter.ChangeType<T>(StringValue);  

班级在下面。

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}

我会为枚举和其他复杂结构添加一个后备转换选项,但是不错。
Tomer W 2012年

2
为什么使用RegisterTypeConverter?我们需要事先注册转换器吗?(很遗憾,链接已死,所以我无法阅读它)
Cohen

对于多次转换,你可能需要创建tc(的TypeConverter)一个唯一的一次。TypeConverter之所以慢是因为它使用反射来搜索TypeConverterAttribute。如果初始化单个私有TypeConverter字段,那么您应该能够重复使用TypeConverter多次。
凯文·莱斯

工作正常,但是如果T为an object,则抛出异常。我能够通过使用`if(typeof(T).IsPrimitive){return TConverter.ChangeType <T>(StringValue); } else {object o =(object)StringValue; 还给; }`代替“用法”示例 TConverter.ChangeType<T>(StringValue)
Matt 2002年

14

对于许多类型(整数,双精度,DateTime等),有一个静态的Parse方法。您可以使用反射调用它:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}

8
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor是具有GetConvertor接受Type对象的方法的类,然后您可以调用ConvertFrommethod来转换该value指定对象的。


我个人认为此接口比方法Convert.ChangeType更适合处理转换,因为您需要在所有类上实现IConvertible接口。
Sauleil '19

3

您可以使用诸如traits class之类的构造。这样,您将拥有一个参数化的帮助程序类,该类知道如何将字符串转换为其自身类型的值。然后您的吸气剂可能如下所示:

get { return StringConverter<DataType>.FromString(base.Value); }

现在,我必须指出,我对参数化类型的经验仅限于C ++及其模板,但我想有某种方法可以使用C#泛型来做同样的事情。


通用版本在C#中不存在。
Shimmy Weitzhandler,2015年

3

检查静态Nullable.GetUnderlyingType。-如果基础类型为null,则模板参数为not Nullable,我们可以直接使用该类型-如果基础类型不为null,则在转换中使用基础类型。

似乎为我工作:

public object Get( string _toparse, Type _t )
{
    // Test for Nullable<T> and return the base type instead:
    Type undertype = Nullable.GetUnderlyingType(_t);
    Type basetype = undertype == null ? _t : undertype;
    return Convert.ChangeType(_toparse, basetype);
}

public T Get<T>(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get<int>("14");
    int? nx = Get<Nullable<int>>("14");
}

1

鲍勃的答案中得到启发,这些扩展还支持空值转换以及所有原始转换。

public static class ConversionExtensions
{
        public static object Convert(this object value, Type t)
        {
            Type underlyingType = Nullable.GetUnderlyingType(t);

            if (underlyingType != null && value == null)
            {
                return null;
            }
            Type basetype = underlyingType == null ? t : underlyingType;
            return System.Convert.ChangeType(value, basetype);
        }

        public static T Convert<T>(this object value)
        {
            return (T)value.Convert(typeof(T));
        }
}

例子

            string stringValue = null;
            int? intResult = stringValue.Convert<int?>();

            int? intValue = null;
            var strResult = intValue.Convert<string>();

0
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

我通过对象使用转换。这有点简单。


谢谢,我必须在接口中转换T,并且简单的转换T对象可以正常,轻松,快速地运行。谢谢
LXG 2012年

5
(int)(object)“ 54”; 是致命的!,这不是VB!
Tomer W 2012年

0

我用lobos回答,它有效。但是由于文化设置,我在转换双打时遇到了问题。所以我加了

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

0

另一个变化。处理Nullable,以及字符串为null而T 不为 null的情况。

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get
        {
            if (base.Value == null) return default(T);
            var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            return (T)Convert.ChangeType(base.Value, type);
        }
        set { base.Value = value.ToString(); }
    }
}

0

您可以在一行中完成此操作,如下所示:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

快乐的编码;)


当您共享代码作为答案时,请尝试对其进行解释。
Yunus Temurlenk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.