当前位置:  开发笔记 > 编程语言 > 正文

C#string解析为变量类型

如何解决《C#string解析为变量类型》经验,为你挑选了3个好方法。

我想轻松地将一个字符串解析成一个类型,但是我不想为每个类型编写包装器代码,我只是希望能够执行"1234".Parse()之类的操作并让它返回1234.应该适用于任何具有解析功能的类型.



1> Mehrdad Afsh..:

这个技巧应该有效.它使用您自动分配的变量类型:

public static class StringExtensions {
    public static ParsedString Parse(this string s) {
        return new ParsedString(s);
    }
}
public class ParsedString {
    string str;
    public ParsedString(string s) {
        str = s;
    }
    public static implicit operator int(ParsedString s) {
        return int.Parse(s.str);
    }
    public static implicit operator double(ParsedString s) {
        return double.Parse(s.str);
    }
    public static implicit operator short(ParsedString s) {
        return short.Parse(s.str);
    }
    public static implicit operator byte(ParsedString s) {
        return byte.Parse(s.str);
    }
    // ... add other supported types ...
}

用法:

int p = "1234".Parse();

我宁愿使用框架提供的方法显式解析,而不是依赖于这些技巧.



2> ckknight..:

我的解决方案适用于任何实现静态方法TryParse(string,out T)的类型,无论它是类还是结构.此外,它将适用于可以为空的结构,例如

"1234".Parse() == 1234
"asdf".Parse() == 0 // i.e. default(int)
"1234".Parse() == 1234
"asdf".Parse() == null
"2001-02-03".Parse() == new DateTime(2009, 2, 3)

因为System.Net.IPAddress有TryParse,

"127.0.0.1".Parse().Equals(new IPAddress(new byte[] { 127, 0, 0, 1 }))

我使用System.Linq.Expressions框架创建代码,然后缓存创建的lambda.由于这是在具有指定类型的通用静态类中完成的,因此每种类型只需解析一次.

public static class StringExtensions
{
    /// 
    /// Parse the  as a . If this cannot be achieved, return the default value of .
    /// 
    /// The type to parse into.
    /// The string to parse.
    /// The resultant  or the default of .
    /// 
    /// 
    /// "1234".Parse<int>() == 1234;
    /// "a".Parse<int>() == 0;
    /// "a".Parse<int?>() == null;
    /// "2010-01-01".Parse<DateTime?>() == new DateTime(2010, 1, 1)
    /// "2010-01-01a".Parse<DateTime?>() == null
    /// "127.0.0.1".Parse<System.Net.IPAddress>().Equals(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }))
    /// "".Parse<System.Net.IPAddress>() == null
    /// 
    /// 
    public static T Parse(this string target)
    {
        return ParseHelper.Parse(target);
    }

    /// 
    /// Parse the  as a . If this cannot be achieved, return 
    /// 
    /// The type to parse into.
    /// The string to parse.
    /// The value to return if  could not be parsed.
    /// The resultant  or .
    /// 
    /// 
    /// "1234".Parse<int>(-1) == 1234;
    /// "a".Parse<int>(-1) == -1;
    /// "2010-01-01".Parse<DateTime?>(new DateTime(1900, 1, 1)) == new DateTime(2010, 1, 1)
    /// "2010-01-01a".Parse<DateTime?>(new DateTime(1900, 1, 1)) == new DateTime(1900, 1, 1)
    /// "127.0.0.1".Parse<System.Net.IPAddress>(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 })).Equals(new System.Net.IPAddress(new byte[] { 127, 0, 0, 1 }))
    /// "".Parse<System.Net.IPAddress>(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 })).Equals(new System.Net.IPAddress(new byte[] { 0, 0, 0, 0 }))
    /// 
    /// 
    public static T Parse(this string target, T defaultValue)
    {
        return ParseHelper.Parse(target, defaultValue);
    }

    private static class ParseHelper
    {
        private static readonly Func _parser;

        static ParseHelper()
        {
            Type type = typeof(T);
            bool isNullable = false;
            if (type.GetGenericArguments().Length > 0 && type.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                isNullable = true;
                type = type.GetGenericArguments()[0];
            }

            ParameterExpression target = Expression.Parameter(typeof(string), "target");
            ParameterExpression defaultValue = Expression.Parameter(typeof(T), "defaultValue");
            ParameterExpression result = Expression.Parameter(typeof(T), "result");
            if (isNullable)
            {
                Type helper = typeof(NullableParseHelper<>);
                helper = helper.MakeGenericType(typeof(T), type);
                MethodInfo parseMethod = helper.GetMethod("Parse");
                _parser = Expression.Lambda>(
                    Expression.Call(parseMethod, target, defaultValue),
                    target, defaultValue, result).Compile();
            }
            else
            {
                MethodInfo tryParseMethod = (from m in typeof(T).GetMethods()
                                             where m.Name == "TryParse"
                                             let ps = m.GetParameters()
                                             where ps.Count() == 2
                                                && ps[0].ParameterType == typeof(string)
                                                && ps[1].ParameterType == typeof(T).MakeByRefType()
                                             select m).SingleOrDefault();

                if (tryParseMethod == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot find method {0}.TryParse(string, out {0})", type.FullName));
                }
                _parser = Expression.Lambda>(
                    Expression.Condition(
                        Expression.Call(tryParseMethod, target, result),
                        result,
                        defaultValue),
                    target, defaultValue, result).Compile();
            }
        }

        public static T Parse(string target)
        {
            return _parser.Invoke(target, default(T), default(T));
        }

        public static T Parse(string target, T defaultValue)
        {
            return _parser.Invoke(target, defaultValue, default(T));
        }

        private static class NullableParseHelper where TBase : struct
        {
            private static readonly Func _parser;

            static NullableParseHelper()
            {
                MethodInfo tryParseMethod = (from m in typeof(TBase).GetMethods()
                                             where m.Name == "TryParse"
                                             let ps = m.GetParameters()
                                             where ps.Count() == 2
                                                && ps[0].ParameterType == typeof(string)
                                                && ps[1].ParameterType == typeof(TBase).MakeByRefType()
                                             select m).SingleOrDefault();

                if (tryParseMethod == null)
                {
                    throw new InvalidOperationException(string.Format("Cannot find method {0}.TryParse(string, out {0})", typeof(TBase).FullName));
                }
                ParameterExpression target = Expression.Parameter(typeof(string), "target");
                ParameterExpression defaultValue = Expression.Parameter(typeof(TBase?), "defaultValue");
                ParameterExpression result = Expression.Parameter(typeof(TBase), "result");
                _parser = Expression.Lambda>(
                    Expression.Condition(
                        Expression.Call(tryParseMethod, target, result),
                        Expression.ConvertChecked(result, typeof(TBase?)),
                        defaultValue),
                    target, defaultValue, result).Compile();
            }

            public static TBase? Parse(string target, TBase? defaultValue)
            {
                return _parser.Invoke(target, defaultValue, default(TBase));
            }
        }
    }
}

裤子!



3> Brandon..:

为什么不能使用已有的解析?

int.Parse("1234");
decimal.Parse("1234");
double.Parse("1234");

如果您不确定它是否能够成功解析,请使用TryParse.

或者,如果您想将其实现为扩展方法,请查看本文,该文章将向您展示如何创建Generic String.Parse方法.

编辑:在我发布答案后,我不知道该网站如何迅速下降.这是本文创建的类:

using System;
using System.ComponentModel;

public static class Parser {

     public static T Parse(this string value) {
        // Get default value for type so if string
        // is empty then we can return default value.
        T result = default(T);

        if (!string.IsNullOrEmpty(value)) {
          // we are not going to handle exception here
          // if you need SafeParse then you should create
          // another method specially for that.
          TypeConverter tc = TypeDescriptor.GetConverter(typeof(T));
          result = (T)tc.ConvertFrom(value);
        }

        return result;
    }
}

例子:

// regular parsing
int i = "123".Parse(); 
int? inull = "123".Parse(); 
DateTime d = "01/12/2008".Parse(); 
DateTime? dn = "01/12/2008".Parse();

// null values
string sample = null;
int? k = sample.Parse(); // returns null
int l = sample.Parse();   // returns 0
DateTime dd = sample.Parse(); // returns 01/01/0001
DateTime? ddn = sample.Parse(); // returns null

推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有