类型转换是我们最常用的功能。就像上战场用的枪一样,敌人用的冲锋枪,
自己手里就一把步枪,打起仗来始终有点不爽。因此,基本功能的完善很重要。通常情况下我们需要 String 类型转其它的基础类型。这时我们最常用的是 Convert 类。比如:
- 1 Convert.ToInt32("23");
- 2 Convert.ToDouble("3.4");
- 3 Convert.ToDateTime("2014-4-4");
但是这个方法一旦出现转换失败将会非常影响程序的效率。
因此这种方式会更为合理:
- 1 int temp;
- 2 bool success = Int32.TryParse("23", out temp);
- 3
- if (!success) 4 {
- 5 temp = 0;
- 6
- }
当然这种方式必须输入更多的代码,对于程序员来说有违人性,我也不想一个简单的转换就要输那么一堆代码。
宝宝表示很不高兴。
因此我自定义了一个 StringContainer 类型
- 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 }
struct 类型是为了让 CLR 能更快的清除 string 类型所占用的内存。当然在内存充足的情况下,class 类型效率要更快一点。
其中定义的 Empty 静态成员也是为了减少内存占用。
- public static readonly StringContainer Empty=new StringContainer();
而 value 是存储字符串用的。StringContainer 是默认初始化函数。
而我们将添加以下函数实现 String 类型到 StringContainer 类型的转换。
- 1 public static implicit operator StringContainer(string value) 2 {
- 3
- return new StringContainer(value);
- 4
- }
有了以上函数,我们就可以这样写:
- StringContainer str = "23";
下面我们将重写强制类型转换运算符,来实现 String 类型到 Int32 类型的自动转换。
- 1 public static implicit operator Int32(StringContainer stringContainar) 2 {
- 3 Int32 result;
- 4 Int32.TryParse(stringContainar.value, out result);
- 5
- return result;
- 6
- }
这个方法意思是说当编译器需要把该类型转为 Int32 时将会默认使用该函数进行转换。
- 1 StringContainer str = "23";
- 2 int num = str;
到底发生了什么呢?我们从 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. 先将 "23" 推向栈顶。
2. 然后调用以 string 为参数的初始化函数。
3. 把 str 初始化的结果保存到本地变量中。
4. 加载 str 到栈顶。
5. 调用以 StringContainer 为参数的转换函数。
6. 最后把结果存储到本地变量 Num 中。
从 IL 代码可以清楚了解。强制类型转换是由 C# 编译器自动完成的。
也就是说任意类型与 StringContainer 类型的相互转换是可以通过添加相应的转换函数实现的。
由于在. net 中函数是静态编码,虽然占用了更多的内存,但在运行时并不会影响程序的运行效率。下面是 StringContainer.tt 模板的详细代码。
- <#@ template debug="false" hostspecific="false" language="C#" #>
- <#@ assembly name="System.Core" #>
- <#@ import namespace="System.Linq" #>
- <#@ import namespace="System.Text" #>
- <#@ import namespace="System.Collections.Generic" #>
- <#@ output extension=".cs" #>
- using System;
- <#var nullableType=new string[]{"String"};#>
- <#var structType=new string[]{"SByte","Byte","Int16","UInt16","Int32","UInt32","Int64","UInt64","Boolean","Char","Decimal","Double","Single","DateTime","DateTimeOffset"};#>
- namespace System
- {
- public struct StringContainer
- {
- public static readonly StringContainer Empty=new StringContainer();
- public string value;
- internal StringContainer(string value)
- {
- this.value = value;
- }
- public override bool Equals(object obj)
- {
- return base.Equals(obj);
- }
- public override int GetHashCode()
- {
- return base.GetHashCode();
- }
- public static bool operator ==(StringContainer container, string str)
- {
- return container.value == str;
- }
- public static bool operator !=(StringContainer container, string str)
- {
- return container.value != str;
- }
- <# for(int i=0;i
- public static implicit operator StringContainer(<#=structType[i]#> obj)
- {
- return new StringContainer(obj.ToString());
- }
- <# }#>
- <# for(int i=0;i
- public static implicit operator StringContainer(<#=structType[i]#>? obj)
- {
- if(obj!=null)
- {
- return new StringContainer(obj.ToString());
- }
- return StringContainer.Empty;
- }
- <# }#>
- public static implicit operator StringContainer(string value)
- {
- return new StringContainer(value);
- }
- public static implicit operator string(StringContainer stringContainar)
- {
- return stringContainar.value;
- }
- <#for(int i=0;i
- public static implicit operator <#=structType[i]#>(StringContainer stringContainar)
- {
- <#=structType[i]#> result;
- <#=structType[i]#>.TryParse(stringContainar.value, out result);
- return result;
- }
- <#}#>
- <#for(int i=0;i
- public static implicit operator <#=structType[i]#>?(StringContainer stringContainar)
- {
- <#=structType[i]#> result;
- if(<#=structType[i]#>.TryParse(stringContainar.value, out result))
- {
- return result;
- }
- else
- {
- return null;
- }
- }
- <#}#>
- }
- }
实现这些基本函数后。我们可以这样写:
- 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;
是不是感觉 StringContainer 有点 var 变量的味道?而且自带自动转换功能。
在之前的 AspNet 以及 asp.net core 中都有一个 Context.Request.Form 的 Collection 类型。
我们是否可以改造该类型呢?
于是我又定义了一个 NameValueCollection 类型
- 1 public class NameValueCollection: IEnumerablestring,
- 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 IEnumeratorstring,
- 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
- }
这样的话,Form 类型是否可以这样写?
- int a=context.request.Form["a"];
- byte? b=context.request.Form["b"];
- float c=context.request.Form["c"];
- DateTime d=context.request.Form["d"];
一个函数的参数类型与参数类型均不确定的函数如何定义?是不是想不到,那我们看看以下函数。
- 1 //函数
- 2 public void Run(params StringContainer[] scArray)
- 3 {
- 4
- 5 }
我们在调用时,仅仅需要 instance.Run(1,"3",4.5,DateTime.Now);
当然也可以这样写:
- 1 public void Run(NameValueCollection nvc)
- 2 {
- 3
- 4 }
调用时:
- 1 NameValueCollection nvc=new NameValueCollection();
- 2 nvc.Add("a",1);
- 3 nvc.Add("b",1.5);
- 4 nvc.Add("c",DateTime.Now);
- 5 instance.Run(nvc);
当然更进一步的话,我们可以利用. net 4.0 的 dynamic 特性实现以下效果:
- int a=context.request.Form.a;
- byte? b=context.request.Form.b;
- float c=context.request.Form.c;
- DateTime d=context.request.Form.d;
具体思路就不在这里讲了。直接贴代码。
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics.CodeAnalysis;
- using System.Dynamic;
- namespace NFinal.Collections
- {
- public class NameValueDynamicCollection: DynamicObject, IDictionary<string, StringContainer>
- {
- private readonly IDictionary<string, StringContainer> _obj;
- public NameValueDynamicCollection()
- {
- _obj = new Dictionary<string, StringContainer>();
- }
- public NameValueDynamicCollection(IDictionary<string, StringContainer> obj)
- {
- _obj = obj;
- }
- public StringContainer this[string key]
- {
- get
- {
- StringContainer result;
- if (_obj.TryGetValue(key, out result))
- {
- return result;
- }
- else
- {
- return StringContainer.Empty;
- }
- }
- set
- {
- if (_obj.ContainsKey(key))
- {
- _obj[key] = value;
- }
- else
- {
- _obj.Add(key, value);
- }
- }
- }
- [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "The compiler generates calls to invoke this")]
- public override bool TryGetMember(GetMemberBinder binder, out object result)
- {
- result = this[binder.Name];
- return true;
- }
- [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "The compiler generates calls to invoke this")]
- public override bool TrySetMember(SetMemberBinder binder, object value)
- {
- if (value == null)
- {
- this[binder.Name] = StringContainer.Empty;
- }
- else
- {
- this[binder.Name] =new StringContainer(value.ToString());
- }
- return true;
- }
- public void Add(string key, StringContainer value)
- {
- if (!_obj.ContainsKey(key))
- {
- _obj.Add(key, value);
- }
- }
- public bool ContainsKey(string key)
- {
- return _obj.ContainsKey(key);
- }
- public ICollection<string> Keys
- {
- get { return _obj.Keys; }
- }
- public bool Remove(string key)
- {
- return _obj.Remove(key);
- }
- public bool TryGetValue(string key, out StringContainer value)
- {
- return _obj.TryGetValue(key, out value);
- }
- public ICollection Values
- {
- get { return _obj.Values; }
- }
- public void Add(KeyValuePair<string, StringContainer> item)
- {
- _obj.Add(item);
- }
- public void Clear()
- {
- _obj.Clear();
- }
- public bool Contains(KeyValuePair<string, StringContainer> item)
- {
- return _obj.Contains(item);
- }
- public void CopyTo(KeyValuePair<string, StringContainer>[] array, int arrayIndex)
- {
- _obj.CopyTo(array, arrayIndex);
- }
- public int Count
- {
- get { return _obj.Count; }
- }
- public bool IsReadOnly
- {
- get { return _obj.IsReadOnly; }
- }
- public bool Remove(KeyValuePair<string, StringContainer> item)
- {
- return _obj.Remove(item);
- }
- public IEnumeratorstring, StringContainer>> GetEnumerator()
- {
- return _obj.GetEnumerator();
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
- }
具体代码实现,请参看 https://git.oschina.net/LucasDot/NFinal2
来源: http://www.cnblogs.com/LucasDot/p/6484109.html