反射类型的默认值(T)

发布于 2024-12-05 20:38:09 字数 2473 浏览 2 评论 0原文

在浏览其他答案时,我想出了以下扩展方法,它很有效:

public static T Convert<T>( this string input )
{
    var converter = TypeDescriptor.GetConverter( typeof( T ) );
    if ( converter != null )
    {
        try
        {
            T result = (T) converter.ConvertFromString( input );
            return result;
        }
        catch
        {
            return default( T );
        }
    }
    return default( T );
}

我可以像这样使用它:

string s = "2011-09-21 17:45";
DateTime result = s.ConvertTo( typeof( DateTime ) );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

太棒了!效果很好。现在,我想对反射类型做类似的事情。我有:

public static dynamic ConvertTo( this string input, Type type )
{
    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            dynamic result = converter.ConvertFromString( input );
            return ( result );
        }
        catch
        {
            return default( type );  // bogus
        }
    }

    return default( type );  // bogus
}

我想这样使用它:

Type someType;  // will be DateTime, int, etc., but not known until runtime
DateTime result = s.ConvertTo( sometype );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

当然,编译器反对 ConvertTo 方法中的“虚假”行。我需要的(好吧,不一定需要,但它会很好)是一种获得与第一个示例相同的结果的方法,这样如果转换失败,可以分配给反射对象的值被返回,并且可以按照与第一个示例中相同的方式进行识别。

编辑:

我完成了什么:

public static dynamic ConvertTo( this string input, Type type, out bool success )
{
    dynamic result;

    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            result = converter.ConvertFromString( input );
            success = true;
            return result;
        }
        catch { /* swallow the exception */ }
    }

    result = type.IsValueType ? Activator.CreateInstance( type ) : null;
    success = false;

    return result;
}

并使用了:

bool success;
string val = "2011-09-21 17:25";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( success )
    doSomethingGood();

val = "foo";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( !success )
    dealWithBadData();

请记住,为了演示的目的,我对 typeof() 位进行了硬编码。在我的应用程序中,类型都得到了反映。

感谢大家的快速答复!

In browsing other answers, I have come up with the following extension method which works a treat:

public static T Convert<T>( this string input )
{
    var converter = TypeDescriptor.GetConverter( typeof( T ) );
    if ( converter != null )
    {
        try
        {
            T result = (T) converter.ConvertFromString( input );
            return result;
        }
        catch
        {
            return default( T );
        }
    }
    return default( T );
}

And I can use it like:

string s = "2011-09-21 17:45";
DateTime result = s.ConvertTo( typeof( DateTime ) );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

Awesome! Works great. Now, I'd like to do something similar with a reflected type. I have:

public static dynamic ConvertTo( this string input, Type type )
{
    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            dynamic result = converter.ConvertFromString( input );
            return ( result );
        }
        catch
        {
            return default( type );  // bogus
        }
    }

    return default( type );  // bogus
}

And I'd like to use it thus:

Type someType;  // will be DateTime, int, etc., but not known until runtime
DateTime result = s.ConvertTo( sometype );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

Of course, the compiler objects to the 'bogus' lines in the ConvertTo method. What I need (ok, don't necessarily need, but it'd be nice) is a way to get the same result as in the first example so that if the conversion fails, something that can be assigned to the reflected object is returned and can be recognized in the same manner as in the first example.

Edit:

What I finished with:

public static dynamic ConvertTo( this string input, Type type, out bool success )
{
    dynamic result;

    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            result = converter.ConvertFromString( input );
            success = true;
            return result;
        }
        catch { /* swallow the exception */ }
    }

    result = type.IsValueType ? Activator.CreateInstance( type ) : null;
    success = false;

    return result;
}

and used:

bool success;
string val = "2011-09-21 17:25";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( success )
    doSomethingGood();

val = "foo";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( !success )
    dealWithBadData();

Remembering that, for the purpose of demonstration, I'm hard-coding the typeof() bit. In my application, the types are all reflected.

Thanks to all for the speedy answers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

客…行舟 2024-12-12 20:38:09

您可以使用

//to get default(T) from an instance of Type
type.IsValueType ? Activator.CreateInstance(type) : null;

This,因为值类型保证有一个默认构造函数,而引用类型的默认值为null

You can use

//to get default(T) from an instance of Type
type.IsValueType ? Activator.CreateInstance(type) : null;

This is because value types are guaranteed to have a default constructor, and the default value of a reference type is a null.

骄兵必败 2024-12-12 20:38:09

如果您使用 typeof(Type) 传递类型,那么显然您可以只使用第一种方法。那么,假设您通过反射获取类型(您说的是),那么您还可以使用反射来获取第一个版本的 Convert()MethodInfo code>,然后使用 MakeGenericMethod() 将您的反射类型替换为它:

MethodInfo m = typeof(MyConvertExtensions).GetMethod("Convert");
MethodInfo invocable = m.MakeGenericMethod(myReflectedType);
invocable.Invoke(null, new[] { myString });

If you're passing in the type using typeof(Type), then obviously you could just use the first method. Assuming, then, that you're getting the type via reflection (which you say you are) then you can also use reflection to get the MethodInfo for your first version of Convert(), and then use MakeGenericMethod() to substitute your reflected type into it:

MethodInfo m = typeof(MyConvertExtensions).GetMethod("Convert");
MethodInfo invocable = m.MakeGenericMethod(myReflectedType);
invocable.Invoke(null, new[] { myString });
月下凄凉 2024-12-12 20:38:09

未经测试,但也许是这样的?

public static dynamic ConvertTo(this string input, Type type)
{
    var converter = TypeDescriptor.GetConverter(type);
    if (converter != null)
    {
        try
        {
            return converter.ConvertFromString(input);
        }
        catch
        {
            // ignore
        }
    }

    if (type.IsValueType)
        return Activator.CreateInstance(type);

    return null;
}

Untested, but maybe something like this?

public static dynamic ConvertTo(this string input, Type type)
{
    var converter = TypeDescriptor.GetConverter(type);
    if (converter != null)
    {
        try
        {
            return converter.ConvertFromString(input);
        }
        catch
        {
            // ignore
        }
    }

    if (type.IsValueType)
        return Activator.CreateInstance(type);

    return null;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文