Nonsense
From. after net3.5 was released, many predecessors used generics to create a lot of interesting code, and the general conversion method was also poorly written. I wrote it again today, I just want to manage my personal knowledge and catch up with Daniel. Please criticize and correct me a lot.
Ideas
1. iconvertible is implemented for all basic types.
2. The tryparse method is implemented for all basic types.
Implementation
Public static class converter {// <summary> // convert to another type that inherits iconvertible /// </Summary> /// <typeparam name = "T"> convert </typeparam> /// <Param name = "value"> value to be converted </param> /// <Param name = "success"> Successful </ param> // <returns> </returns> Public static t to <t> (this iconvertible value, out bool success) where T: iconvertible {If (value = NULL) {success = true; return default (t);} type tresult = typeof (T); If (tresult = typeof (string) {success = true; Return (t) (object) value. tostring ();} methodinfo mtryparse = tresult. getmethod ("tryparse", bindingflags. public | bindingflags. static, type. defaultbinder, new type [] {typeof (string), tresult. makebyreftype ()}, new parametermodifier [] {New parametermodifier (2)}); var parameters = new object [] {value. tostring (), default (t)}; success = (bool) mtryp Arse. Invoke (null, parameters); Return success? (T) parameters [1]: default (t );} /// <summary> /// convert to another type that inherits iconvertible /// </Summary> /// <typeparam name = "T"> Conversion Type </typeparam >/// <Param name = "value"> value to be converted </param> /// <returns> </returns> Public static t to <t> (this iconvertible value) where T: iconvertible {bool success; return to <t> (value, out success );}}Unit Test
[TestClass] public class UnitTessConverter { [TestMethod] public void TestTo() { int i = 1; double dResult = i.To<double>(); Assert.AreEqual(i, 1d); Assert.AreEqual(‘1‘, i.To<char>()); double d = 1.1d; int iResult = d.To<int>(); Assert.AreEqual(0, iResult); float fResult = d.To<float>(); Assert.AreEqual(1.1f, fResult); d = 1d; Assert.AreEqual(1, d.To<int>()); float f = 1.1f; iResult = f.To<int>(); Assert.AreEqual(0, iResult); string str = "1.1"; Assert.AreEqual(1.1f, str.To<float>()); Assert.AreEqual(1.1d, str.To<double>()); Assert.AreEqual((decimal)1.1, str.To<decimal>()); str = "1990-10-1 12:00"; Assert.AreEqual(new DateTime(1990, 10, 1, 12, 0, 0), str.To<DateTime>()); str = "100dd"; bool success; Assert.AreEqual(DateTime.MinValue, str.To<DateTime>(out success)); Assert.IsFalse(success); Assert.AreEqual(0, str.To<int>(out success)); Assert.IsFalse(success); Assert.AreEqual(0, str.To<double>(out success)); Assert.IsFalse(success); Assert.AreEqual(‘\0‘, str.To<char>(out success)); Assert.IsFalse(success); str = null; fResult = str.To<float>(); Assert.AreEqual(0f, fResult); Assert.AreEqual("Hibernating", MachineState.Hibernating.To<string>()); Assert.AreEqual(0, MachineState.PowerOff.To<int>()); } enum MachineState { PowerOff = 0, Running = 5, Sleeping = 10, Hibernating = Sleeping + 5 } }
Test passed
Test the running efficiency
Computer Configuration:
Efficiency Test code:
class Program { static void Main(string[] args) { System.Diagnostics.Stopwatch st = new System.Diagnostics.Stopwatch(); st.Start(); for (int i = 0; i < 1000000; i++) { i.To<string>().To<double>().To<float>(); } st.Stop(); Console.WriteLine(st.ElapsedMilliseconds); Console.Read(); } }
First: 19639
Second: 19414
Third: 19262
Optimization
In the above to method, reflection is used. Reflection is a performance killer and should be avoided as much as possible. Therefore, I thought of saving the methodinfo object "tryparse" obtained by reflection.
Optimized Code:
Public static class converter {// <summary> // convert to another type that inherits iconvertible /// </Summary> /// <typeparam name = "T"> convert </typeparam> /// <Param name = "value"> value to be converted </param> /// <Param name = "success"> Successful </ param> // <returns> </returns> Public static t to <t> (this iconvertible value, out bool success) where T: iconvertible {If (value = NULL) {success = true; return default (t);} type tresult = typeof (T); If (tresult = typeof (string) {success = true; Return (t) (object) value. tostring ();} methodinfo mtryparse; If (_ tryparse. containskey (tresult. fullname) {mtryparse = _ tryparse [tresult. fullname];} else {mtryparse = tresult. getmethod ("tryparse", bindingflags. public | bindingflags. static, type. defaultbinder, new type [] {typeof (string), tresult. makebyreftype ()}, new parametermodifier [] {New Parametermodifier (2)}); _ tryparse. add (tresult. fullname, mtryparse);} var parameters = new object [] {value. tostring (), default (t)}; success = (bool) mtryparse. invoke (null, parameters); Return success? (T) parameters [1]: default (t );} /// <summary> /// convert to another type that inherits iconvertible /// </Summary> /// <typeparam name = "T"> Conversion Type </typeparam >/// <Param name = "value"> value to be converted </param> /// <returns> </returns> Public static t to <t> (this iconvertible value) where T: iconvertible {bool success; return to <t> (value, out success);} Private Static dictionary <string, methodinfo> _ tryparse = new dictionary <string, methodinfo> ();}
Run the unit test again. The result is
Run the efficiency test code again"
First: 11836
Second: 12170
Third: 11866
This article has ended. I hope you can give me more instructions.