Type conversion is our most commonly used function. Like a gun on the battlefield, the enemy's submachine gun.
1 Convert.ToInt32("23"); 2 Convert.ToDouble("3.4"); 3 Convert.ToDateTime("2014-4-4");
However, once the conversion fails, the efficiency of the program will be greatly affected.
Therefore, this approach would be more reasonable:
1 int temp; 2 bool success= Int32.TryParse("23",out temp); 3 if(!success) 4 { 5 temp=0; 6 }
Of course, this method has to input more code. It's against human nature for programmers. I don't want to lose so much code for a simple conversion.
The baby said he was very unhappy.
So I customized a StringContainer type
1 public struct StringContainer 2 { 3 public static readonly StringContainer Empty=new StringContainer(); 4 public string value; 5 internal StringContainer(string value) 6 { 7 this.value = value; 8 } 9 }
It looks good. The struct type is designed to allow the CLR to clear the memory occupied by the string type more quickly. Of course, class types are more efficient when there is enough memory.
The Empty static members are also defined to reduce memory footprint.
public static readonly StringContainer Empty=new StringContainer();
value is used to store strings. StringContainer is the default initialization function.
We will add the following functions to convert String type to StringContainer type.
1 public static implicit operator StringContainer(string value) 2 { 3 return new StringContainer(value); 4 }
With the above functions, we can write as follows:
StringContainer str = "23";
Next, we will rewrite the mandatory type conversion operator to achieve automatic conversion from String type to Int32 type.
1 public static implicit operator Int32(StringContainer stringContainar) 2 { 3 Int32 result; 4 Int32.TryParse(stringContainar.value, out result); 5 return result; 6 }
This method means that when the compiler needs to convert this type to Int32, it will use this function by default.
1 StringContainer str = "23"; 2 int num = str;
What happened? We analyze the code from IL.
// Method begins at RVA 0x2130 // Code size 20 (0x14) .maxstack 1 .locals init ( [0] valuetype [NFinal4]System.StringContainer str, [1] int32 num ) IL_0000: nop IL_0001: ldstr "23" IL_0006: call valuetype [NFinal4]System.StringContainer [NFinal4]System.StringContainer::op_Implicit(string) IL_000b: stloc.0 IL_000c: ldloc.0 IL_000d: call int32 [NFinal4]System.StringContainer::op_Implicit(valuetype [NFinal4]System.StringContainer) IL_0012: stloc.1 IL_0013: ret
1. Push "23" to the top of the stack first.
2. Then call the initialization function with string as the parameter.
3. Save the results of str initialization into local variables.
4. Load str to the top of the stack.
5. Call the transformation function with StringContainer as the parameter.
6. Finally, the results are stored in the local variable Num.
You can see clearly from the IL code. Mandatory type conversion is done automatically by the C# compiler.
That is to say, the conversion between any type and StringContainer type can be achieved by adding corresponding conversion functions.
Because the function is statically coded in. net, it occupies more memory, but it does not affect the efficiency of the program at run time.
After implementing these basic functions. We can write as follows:
1 StringContainer str="23"; 2 int b=str*4; 3 str=DateTime.Now; 4 str.ToString(); 5 str=4.33; 6 double a=str+1;
Does StringContainer smell like a var variable?
In previous AspNet and asp.net core, there was a Collection type of Context.Request.Form.
Can we change this type?
So I defined a NameValueCollection type
1 public class NameValueCollection : IEnumerable<KeyValuePair<string, StringContainer>> 2 { 3 public NameValueCollection() 4 { 5 collection = new Dictionary<string, StringContainer>(StringComparer.Ordinal); 6 } 7 private IDictionary<string, StringContainer> collection = null; 8 9 public StringContainer this[string key] 10 { 11 get { 12 if (collection.ContainsKey(key)) 13 { 14 return collection[key]; 15 } 16 else 17 { 18 return StringContainer.Empty; 19 } 20 } 21 set { 22 if (value.value==null) 23 { 24 if (collection.ContainsKey(key)) 25 { 26 collection.Remove(key); 27 } 28 } 29 else 30 { 31 if (collection.ContainsKey(key)) 32 { 33 collection[key] = value; 34 } 35 else 36 { 37 collection.Add(key, value); 38 } 39 } 40 } 41 } 42 public void Add(string key, string value) 43 { 44 this[key]=value; 45 } 46 47 public IEnumerator<KeyValuePair<string, StringContainer>> GetEnumerator() 48 { 49 return collection.GetEnumerator(); 50 } 51 52 public override string ToString() 53 { 54 StringWriter sw = new StringWriter(); 55 bool firstChild = true; 56 foreach (var item in collection) 57 { 58 if (firstChild) 59 { 60 firstChild = false; 61 } 62 else 63 { 64 sw.Write("&"); 65 } 66 sw.Write(item.Key); 67 sw.Write("="); 68 sw.Write(NFinal.Utility.UrlEncode(item.Value)); 69 } 70 return sw.ToString(); 71 } 72 73 IEnumerator IEnumerable.GetEnumerator() 74 { 75 return collection.GetEnumerator(); 76 } 77 }
In this case, can the Form type be written like this?
1 int a=Context.request.Form["aa"];
Further, of course, we can use the dynamic features of. net 4.0 to achieve the following effects:
int a=context.request.Form.a;
The specific ideas will not be mentioned here.
For details, see https://git.oschina.net/LucasDot/NFinal2