Compile a common C # preprocessing type conversion method using generics,
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:
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.
C # For simple generic programming #
Public class Test <T>: List <T>
{
Public int Count
{
Get {return base. Count ;}
}
Public void Add (T value)
{
If (Count <10)
Base. Add (value );
Else
Throw new IndexOutOfRangeException ();
}
}
------------------
I wrote it myself and passed the test. I hope it will help you :)
Can I use Net20 generic functions to compile a general method to take the maximum value? The function prototype is as follows: public static T Min <T> (T item1, pa
Int a = 0;
For (int I = 1; I <= items. length-1; I ++)
{
If (items [I-1]> items [I])
{
A = I-1
}
Else
{
A = I;
}
Items = itmes [a];
}