利用自动类型转换存储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 ...
随机推荐
- UVa 727 - Equation
题目大意:给一个中缀表达式,转换成后缀表达式. 这类题一直不太会,让我想就是建一棵表达式树,然后后续遍历算了,可是建树的过程实在太麻烦了.今天才看到有中缀表达式转换成后缀表达式的算法,可以用栈进行实现 ...
- java系列--JDBC连接oracle
<oracle开发实战经典><oracle DBA从入门到精通> JDBC连接数据库 JNDI连接池 oracle.jdbc.driver.OracleDriver 其实就是一 ...
- centos6 安装mysql
如果要在Linux上做j2ee开发,首先得搭建好j2ee的开发环境,包括了jdk.tomcat.eclipse的安装(这个在之前的一篇随笔中已经有详细讲解了Linux学习之CentOS(七)--Cen ...
- CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动
CentOS6.7下使用非root用户(普通用户)编译安装与配置mysql数据库并使用shell脚本定时任务方式实现mysql数据库服务随机自动启动1.关于mysql?MySQL是一个关系型数据库管理 ...
- 【转】sql语句的优化分析
开门见山,问题所在 sql语句性能达不到你的要求,执行效率让你忍无可忍,一般会时下面几种情况. 网速不给力,不稳定. 服务器内存不够,或者SQL 被分配的内存不够. sql语句设计不合理 没有相应的索 ...
- codeforces 755C. PolandBall and Forest
C. PolandBall and Forest time limit per test 1 second memory limit per test 256 megabytes input stan ...
- jQuery原型技术分解
jQuery原型技术分解 起源----原型继承 用户过javascript的都会明白,在javascript脚本中到处都是 函数,函数可以归置代码段,把相对独立的功能封闭在一个函数包中.函数也可以实现 ...
- 使用IntelliJ IDEA开发SpringMVC网站(一)开发环境
使用IntelliJ IDEA开发SpringMVC网站(一)开发环境 摘要: 主要讲解初期的开发环境搭建,Maven的简单教学. 访问GitHub下载最新源码:https://github.com/ ...
- 开源第三方登录组件OAuthLogin2.0 解析及开源地址
OAuthLogin2.0介绍地址: 博客地址:http://www.cnblogs.com/dazhuangtage/p/6306133.html Nuget地址:https://www.nuget ...
- POJ2479(dp)
Maximum sum Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39089 Accepted: 12221 Des ...