puclic static implicit operator Ip(string ip) { Ip iptemp=new Ip(ip); return iptemp; }
使用类型内置的Parse、TryParse、 ToString、ToDouble、 ToDateTime算法
使用CLR支持的类型:父类和子类之间的转换。数据库
为了编译更强壮的代码,建议更常使用as和is安全
何时使用aside
何时使用is函数
这个确定好,不说了。安全ui
基元类型为何须要为null?考虑两个场景:this
写法: int?i=null;code
语法T?是Nullable<T>的简写,二者能够相互转换。能够为null的类型表示其基础值类型正常范围内的值再加上一个null值。例如,Nullable<Int32>,其值的范围为-2 147 483 648~2 147 483 647,再加上一个null值。orm
?常常和??配合使用,好比:对象
int?i=123; int j=i??0;
使用const的理由只有一个,那就是效率。之因此说const变量的效率高,是由于通过编译器编译后,咱们在代码中引用const变量的地方会用const变量所对应的实际值来代替。好比: const=100, const和100被使用的时候是等价,const自带static光圈。
const和readonly的本质区别以下:
容许使用的枚举类型有byte、sbyte、short、ushort、int、uint、long和ulong。应该始终将0值做为枚举类型的默认值。不过,这样作不是由于容许使用的枚举类型在声明时的默认值是0值,而是有工程上的意义。
既然枚举类型从0开始,这样能够避免一个星期多出来一个0值。
不要给枚举设定值。有时候有某些增长的须要,会为枚举添加元素,在这个时候,就像咱们为枚举增长元素ValueTemp同样,极有可能会一不当心增长一个无效值。
好比:Salary familyIncome=mikeIncome+roseIncome; 阅读一目了然。经过使用opera-tor关键字定义静态成员函数来重载运算符,让开发人员能够像使用内置基元类型同样使用该类型。
有特殊须要比较的时候就考虑。集合排序比较经过linq 也能够解决。
不管是操做符“==”仍是方法“Equals”,都倾向于表达这样一个原则:
对于引用类型,若是类型指向同一个对象,则返回True。
注意
注意
重写Equals方法的同时,也应该实现一个类型安全的接口IEquatable<T>,好比 :class Person:IEquatable
有两种方法能够为类型提供格式化的字符串输出。
一个典型的格式化器应该继承接口IFormatProvider和ICustomFomatter
浅拷贝
将对象中的全部字段复制到新的对象(副本)中。其中,值类型字段的值被复制到副本中后,在副本中的修改不会影响到源对象对应的值。而引用类型的字段被复制到副本中的是引用类型的引用,而不是引用的对象,在副本中对引用类型的字段值作修改会影响到源对象自己。
深拷贝
一样,将对象中的全部字段复制到新的对象中。不过,不管是对象的值类型字段,仍是引用类型字段,都会被从新建立并赋值,对于副本的修改,不会影响到源对象自己。
不管是浅拷贝仍是深拷贝,微软都建议用类型继承IClone-able接口的方式明确告诉调用者:该类型能够被拷贝。固然,ICloneable接口只提供了一个声明为Clone的方法,咱们能够根据需求在Clone方法内实现浅拷贝或深拷贝。
class Employee:ICloneable { public string IDCode {get;set;} public int Age {get;set; } public Department Department{get;set;} #region ICloneable成员 public object Clone() { return this.MemberwiseClone(); } #endregion } class Department { public string Name {get;set;} public override string ToString() { return this.Name; } }
注意到Employee的IDCode属性是string类型。理论上string类型是引用类型,可是因为该引用类型的特殊性(不管是实现仍是语义),Object.MemberwiseClone方法仍旧为其建立了副本。也就是说,在浅拷贝过程,咱们应该将字符串当作是值类型。
class Employee:ICloneable { public string IDCode{get;set;} public int Age{get;set;} public Department Department{get;set;} #region ICloneable成员 public object Clone() { using(Stream objectStream=new MemoryStream()) { IFormatter formatter=new BinaryFormatter(); formatter.Serialize(objectStream,this); objectStream.Seek(0,SeekOrigin.Begin); return formatter.Deserialize(objectStream)as Employee; } } #endregion}
同时实现深拷贝和浅拷贝
因为接口ICloneable只有一个模棱两可的Clone方法,因此,若是要在一个类中同时实现深拷贝和浅拷贝,只能由咱们本身实现两个额外的方法,声明为DeepClone和Shallow。Em-ployee的最终版本看起来应该像以下的形式:
[Serializable] class Employee:ICloneable { public string IDCode{get;set;} public int Age{get;set;} public Department Department{get;set;} #region ICloneable成员 public object Clone() { return this.MemberwiseClone(); } #endregion public Employee DeepClone() { using(Stream objectStream=new MemoryStream()) { IFormatter formatter=new BinaryFormatter(); formatter.Serialize(objectStream,this); objectStream.Seek(0,SeekOrigin.Begin); return formatter.Deserialize(objectStream)as Employee; } } public Employee ShallowClone() { return Clone()as Employee; }}
dynamic是Framework 4.0的新特性。dynamic的出现让C#具备了弱语言类型的特性。编译器在编译的时候再也不对类型进行检查,编译器默认dynamic对象支持开发者想要的任何特性。
好比,即便你对GetDynamicObject方法返回的对象一无所知,也能够像以下这样进行代码的调用,编译器不会报错:
dynamic dynamicObject=GetDynamicObject(); Console.WriteLine(dynamicObject.Name); Console.WriteLine(dynamicObject.SampleMethod());
固然,若是运行时dynamicObject不包含指定的这些特性(如上文中带返回值的方法SampleMethod),运行时程序会抛出一个RuntimeBinderException异常:“System.Dynamic.ExpandoObject”未包含“Sam-pleMethod”的定义。
var与dynamic有巨大的区别
反射使用
DynamicSample dynamicSample=new DynamicSample(); var addMethod=typeof(DynamicSample).GetMethod("Add"); int re=(int)addMethod.Invoke(dynamicSample,new object[] {1,2});
dynamic dynamicSample2=new DynamicSample(); int re2=dynamicSample2.Add(1,2); //在使用dynamic后,代码看上去更简洁了,而且在可控的范围内减小了一次拆箱的机会。经验证,频繁使用的时候,消耗时间更少
建议:始终使用dynamic来简化反射实现。
总结
在大部分应用状况下,“效率”并无那么高的地位,灵活性更重要。在部分状况下,“灵活性”并无那么高的地位,效率最重要。