使用C#,不使用任何Parse,TryParse,Convert方法,将数字字符串转换成整数

来源:互联网 发布:王心凌honey 知乎 编辑:程序博客网 时间:2024/06/05 03:55

听朋友说,遇到这样的一个面试题,然后来问我,想了半天,居然没有找到好办法,又去问了问PDF.NET开发框架 技术群里面的朋友,群友 laoliu给了一个非常简单的方法,值得推荐:

 char[] digits = "12345".ToCharArray();            int result = 0;            foreach (char c in digits)            {                result = (result * 10) + (c - '0');            }            Console.Write(result);


 

后来自己想了想,是否可以试试反射或者表达式树,写了如下的代码:

使用Emit 方式来转换:

public delegate int UseStringToInt(string input);        static UseStringToInt BuildStringToInt()        {            //            // 下面的代码将创建类似的方法:            // int Fun("123")(return 123;);            //             DynamicMethod method = new DynamicMethod("MyConvert", typeof(int), new Type[] { typeof(string) });            // 获取动态函数的 IL 生成器            var il = method.GetILGenerator();            // 创建一个本地变量,主要用于 Object Type to Propety Type            var local = il.DeclareLocal(typeof(int), true);            // 加载第 1 个参数的 value            il.Emit(OpCodes.Ldarg_0);            il.Emit(OpCodes.Unbox, typeof(int));// 拆箱 string = (string)object; 不同类型的拆箱会出现问题            il.Emit(OpCodes.Stloc, local);// 将上面的拆箱或转换,赋值到本地变量,现在这个本地变量是一个与目标函数相同数据类型的字段了。            il.Emit(OpCodes.Ret);   // 返回            return (UseStringToInt)method.CreateDelegate(typeof(UseStringToInt));        }        


本来以为使用IL代码的Unbox指令,强行将字符串拆箱出来,很可惜,运行的时候提示“代码不稳定,不能运行。”

再试试委托,但使用前先定义个简单的对象:

 public class TestClass    {        private int _value = 500;        public int Value        {            get            {                return _value;            }            set            {                _value = value;            }        }    }


接着使用下面的委托,听说这种方式是访问对象属性最快的方式,可以考虑在ORM中使用:

 //得到指定的属性            System.Reflection.PropertyInfo p = typeof(TestClass).GetProperty("Value", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);            //创建get,set委托            TestClass t = new TestClass();            Func<int> PGet = Delegate.CreateDelegate(typeof(Func<int>), t, p.GetGetMethod(true)) as Func<int>;            Action<int> PSet = Delegate.CreateDelegate(typeof(Action<int>), t, p.GetSetMethod(true)) as Action<int>;            //访问属性            PSet(5);            int i = PGet();


可惜,上面的代码中Action不能指定String参数,否则会有运行时错误;

 

还想到一招,就是使用CodeDom,将字符串形式的代码写进去,然后再动态编译了,代码量太复杂了,这就不讲了。

 

最后,想到一个“偏方”,可以使用对象的序列化和反序列化:

//不使用Parse,TryParse,Convert等,将字符串 "12345" 转换成一个整数            //使用XML序列化的方式,重新设置转换的值            TestClass t2 = new TestClass();            t2.Value = 100;            XmlSerializer xs = new XmlSerializer(typeof(TestClass));            System.IO.MemoryStream ms = new System.IO.MemoryStream();            xs.Serialize(ms, t2);            String s = System.Text.Encoding.UTF8.GetString(ms.ToArray());            string newValue = "12345";            string replaceString = "<Value>100</Value>";            s = s.Replace(replaceString, "<Value>" + newValue + "</Value>");            byte[] bs2 = System.Text.Encoding.UTF8.GetBytes(s);            MemoryStream ms2 = new MemoryStream(bs2);            TestClass t3 = (TestClass)xs.Deserialize(ms2);            int result = t3.Value;


实验成功,但显然这种代码没有laoliu的方式好,也算是一种解决方案吧。

 

原创粉丝点击