利用自动类型转换存储string类型
字符串处理是我们最常用的功能,尤其是与其它类型的相互转也会经常使用。
Convert.ToInt32("");
Convert.ToDouble("3.4");
Convert.ToDateTime("2014-4-4");
但是这个方法一旦出现转换失败将会非常影响程序的效率。
因此这种方式会更为合理:
int temp;
bool success= Int32.TryParse("",out temp);
if(!success)
{
temp=;
}
当然这种方式必须输入更多的代码,对于程序员来说有违人性,我也不想一个简单的转换就要输那么一堆代码。
宝宝表示很不高兴,于是定义了一个StringContainer类型以解决类似问题。
//能够存储基本类型
public void Test1()
{
StringContainer a= ;
StringContainer b="";
StringContainer c=DateTime.Now;
}
//能够自动转换类型
public void Test2(StringContainer d)
{
StringContainer a="";
int b= a + ;
DataTime c=a;
Console.Write(d);
}
//能够调用同一个函数,但参数类型可以不一样
public void Test3()
{
Test2();
Test2(1.2f);
Test2(DateTime.Now);
}
StringContainer类型的精简定义如下,只实现了Int32与String类型的互转:
public struct StringContainer
{
public static readonly StringContainer Empty=new StringContainer();
public string value;
internal StringContainer(string value)
{
this.value = value;
}
public static implicit operator StringContainer(string value)
{
return new StringContainer(value);
}
public static implicit operator string(StringContainer stringContainar)
{
return stringContainar.value;
}
public static implicit operator Int32(StringContainer stringContainar)
{
Int32 result;
Int32.TryParse(stringContainar.value, out result);
return result;
}
public static implicit operator StringContainer(Int32 obj)
{
return new StringContainer(obj.ToString());
}
}
而其中的StringContainer(string value)函数实现String类型到StringContainer类型的转换。
public static implicit operator StringContainer(string value)
{
return new StringContainer(value);
}
有了以上函数,我们就可以这样写:
StringContainer str = "23";
其中的Int32函数实现了String类型到Int32类型的自动转换。
public static implicit operator Int32(StringContainer stringContainar)
{
Int32 result;
Int32.TryParse(stringContainar.value, out result);
return result;
}
通过以上两个函数,我们可以这样写,是不是比Conert类和TryParse函数简单多了?
StringContainer str = "23";
int num = str;
到底内部是怎样转换的呢?我们从IL上分析代码。
// Method begins at RVA 0x2130
// Code size 20 (0x14)
.maxstack
.locals init (
[] valuetype [NFinal4]System.StringContainer str,
[] 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类型的相互转换是可以通过添加相应的转换函数实现的。
为了支持所有基本类型的相互转换,可以添加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=;i<structType.Length;i++){#>
public static implicit operator StringContainer(<#=structType[i]#> obj)
{
return new StringContainer(obj.ToString());
}
<# }#>
<# for(int i=;i<structType.Length;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=;i<structType.Length;i++){#>
public static implicit operator <#=structType[i]#>(StringContainer stringContainar)
{
<#=structType[i]#> result;
<#=structType[i]#>.TryParse(stringContainar.value, out result);
return result;
}
<#}#>
<#for(int i=;i<structType.Length;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;
}
}
<#}#>
}
}
实现这些基本函数后。我们可以这样写:
StringContainer str="";
int b=str*;
str=DateTime.Now;
str.ToString();
str=4.33;
double? a=str+;
是不是感觉StringContainer有点var变量的味道?而且自带自动转换功能。
在之前的AspNet以及asp.net core中都有一个Context.Request.Form的Collection类型。
我们是否可以改造该类型呢?
于是我又定义了一个NameValueCollection类型
public class NameValueCollection : IEnumerable<KeyValuePair<string, StringContainer>>
{
public NameValueCollection()
{
collection = new Dictionary<string, StringContainer>(StringComparer.Ordinal);
}
private IDictionary<string, StringContainer> collection = null; public StringContainer this[string key]
{
get {
if (collection.ContainsKey(key))
{
return collection[key];
}
else
{
return StringContainer.Empty;
}
}
set {
if (value.value==null)
{
if (collection.ContainsKey(key))
{
collection.Remove(key);
}
}
else
{
if (collection.ContainsKey(key))
{
collection[key] = value;
}
else
{
collection.Add(key, value);
}
}
}
}
public void Add(string key, string value)
{
this[key]=value;
} public IEnumerator<KeyValuePair<string, StringContainer>> GetEnumerator()
{
return collection.GetEnumerator();
} public override string ToString()
{
StringWriter sw = new StringWriter();
bool firstChild = true;
foreach (var item in collection)
{
if (firstChild)
{
firstChild = false;
}
else
{
sw.Write("&");
}
sw.Write(item.Key);
sw.Write("=");
sw.Write(NFinal.Utility.UrlEncode(item.Value));
}
return sw.ToString();
} IEnumerator IEnumerable.GetEnumerator()
{
return collection.GetEnumerator();
}
}
这样的话,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"];
一个函数的参数类型与参数类型均不确定的函数如何定义?是不是想不到,那我们看看以下函数。
//函数
public void Run(params StringContainer[] scArray)
{
}
我们在调用时,仅仅需要instance.Run(1,"3",4.5,DateTime.Now);
当然也可以这样写:
public void Run(NameValueCollection nvc)
{ }
调用时:
NameValueCollection nvc=new NameValueCollection();
nvc.Add("a",);
nvc.Add("b",1.5);
nvc.Add("c",DateTime.Now);
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 = "", 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 = "", 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<StringContainer> 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 IEnumerator<KeyValuePair<string, StringContainer>> GetEnumerator()
{
return _obj.GetEnumerator();
} IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
具体代码实现,请参看https://git.oschina.net/LucasDot/NFinal2
利用自动类型转换存储string类型的更多相关文章
- oracle Clob类型转换成String类型
转载:https://www.cnblogs.com/itmyhome/p/4131339.html Clob类型转换成String类型 oracle中表结构如下: create table GRID ...
- Clob类型转换成String类型
oracle中表结构如下: create table GRID_RESOURCE ( ID VARCHAR2(50), CNNAME VARCHAR2(50), TYPE VARCHAR2(50), ...
- 强制类型转换之String类型
㈠布尔(Boolean)类型 布尔值只有两个,主要用来做逻辑判断 true 表示真 : false 表示假 使用typeof检查一个布尔值时,会返回boolean ㈡Null和Unde ...
- Java中Clob类型转换成String类型的问题
1.问题: 项目中使用druid+达梦数据库(基本类似Oracle),查出的Clob类型数据在运行时为ClobProxyImpl对象而不是内容,不能转为字符串 2.原代码: map为达梦数据库或Ora ...
- 如何将Object类型转换成String类型
1. Object.toString() obj.toString() 注意:必须保证Object不是null值,否则将抛出NullPointerException异常. 2. (String)Obj ...
- oracle.sql.Clob类型转换成String类型
方法一: public String ClobToString(Clob clob) throws SQLException, IOException { String reString = &quo ...
- c++ 将float 类型转换成string 类型
string Convert(float Num) { ostringstream oss; oss<<Num; string str(oss.str()); return str; }
- 总结:String类型与Int类型的转换【实现插入操作主键自增】
1.String类型(此类型是数字格式的字符串类型)转换成Int类型 String str = "10000"; 转换成Int类型: int num = Integer.parse ...
- Date类型与String类型的相关问题
今天完成boss交代的任务时,遇到Date类型与String类型的相关问题,参考了网上的一些例子,并且自己写了demo,现在记录下了总结一下: (一)判断一个字符串是不是合法的日期格式 public ...
随机推荐
- 在windows上搭建ipv6代理
事出有因,学校每天12:00之后断网,断网之后怎么办?难道直接睡了?我不甘心. 幸好学校还是留有余地,在断网之后,还是能够上ipv6的,只是现阶段互联网对ipv6支持很不理想,怎么办?刚刚发现 ...
- VPS 上ubuntu 里搭建VPN服务器
根据https://my.oschina.net/isnail/blog/363151里逐步完成,自己本机WIN10连接不成功,VM里面用WIN7连接也不行,找别人试连却成功了,然后自己用手机4G网络 ...
- Grunt安装中遇到的问题汇总
Grunt安装中遇到的问题汇总 1.如果是windows下的dos中安装Grunt,必须以管理员身份登录(第一个坑) 登录方法是: 方法一:开始>所有程序>附件>命令提示符上右键&g ...
- Python3基础 内嵌函数 简单示例
镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...
- HTML/CSS/JavaScript学习总结(转)
HTML 网站开发的主要原则是: – 用标签元素HTML描述网页的内容结构: – 用CSS描述网页的排版布局: – 用JavaScript描述网页的事件处理,即鼠标或键盘在网页元素上的动作后的程序 H ...
- iOS开发之内存缓存机制
使用缓存的目的是为了使用的应用程序能更快速的响应用户输入,是程序高效的运行.有时候我们需要将远程web服务器获取的数据缓存起来,减少对同一个url多次请求. 内存缓存我们可以使用sdk中的NSURLC ...
- #图# #最大生成树# #kruskal# ----- OpenJudge 799:Heavy Transportation
OpenJudge 799:Heavy Transportation 总时间限制: 3000ms 内存限制: 65536kB 描述BackgroundHugo Heavy is happy. Afte ...
- Flash中图片的逐步加载
在Flash中,有Loader类,可以从外部载入一张图片(或swf文件).但是有个不好的地方就是,不像浏览器那样一边下载一边显示.所幸的是,Flash提供了Loader.loadBytes方法和URL ...
- HTML5 JavaScript API
W3C官方指定的HTML5规范已经修订了很多次,HTML5这个概念是与javascript API相捆绑的语义标记.在过去这些年中,HTML5这个词所指代的范围正以惊人的的速度膨胀,某种程度上已经成为 ...
- windows下composer安装不了或composer命令无效的解决办法
安装方法: http://docs.phpcomposer.com/00-intro.html#Installation-Windows (官方中文帮助文档) 问题描述1: 通过Composer-Se ...