cnblogs.com/zhan520g/p/11014918.html
1.正确操作字符串
2.使用默认的转换方式
类型转换运算符:每种类型都有一个方法(运算符),分为隐式转换和显式转换。
自己实现隐式转换:
puclic static implicit operator Ip(string ip)
{
Ip iptemp=new Ip(ip);
return iptemp;
}
使用类型内置 Parse、TryParse、ToString、ToDouble、ToDateTime
使用辅助类System.Convert类、System.BitConverter类提供的方法进行类型转换。
CLR 支持的类型: 父类和子类之间的转换。
3. 区别对待强制转型
为了编译出更健壮的代码,建议使用 as 和 is 更频繁
什么时候用作
如果类型追溯到一个共同的基类,那么基于这个基类的转换(即基类转换为子类本身)应该使用as。 对于子类之间的转换,应该提供转换运算符进行强制转换。
as 运算符从不抛出异常。 如果类型不匹配(转换对象的运行时类型既不是转换后的目标类型也不是其派生类型),或者转换的源对象为null,那么转换后的值也为null。
什么时候使用是
as 运算符有一个问题,它不能对原始类型进行操作。 如果涉及原始类型的算法,需要在is转换前根据类型进行判断,避免转换失败。
4. TryParse 优于 Parse
这个肯定不错,不说了。 安全
5.使用整数? 确保值类型也可以为null
为什么原始类型需要为空? 考虑两种情况:
写法:int ? 我=空;
语法 T? 是Nullable<T>的简写,两者可以相互转换。 可空类型表示在其基础值类型的正常范围内的值加上一个空值。 比如Nullable<Int32>,它的取值范围是-2 147 483 648到2 147 483 647,加上一个空值。
? 经常与? ? 结合使用,例如:
int?i=123;
int j=i??0;
6.区分readonly和const的用法
使用 const 的原因只有一个,那就是效率。 const变量之所以高效,是因为经过编译器编译后,我们在代码中引用const变量的地方,会被const变量对应的实际值所取代 。 例如:const=100,const和100在使用时是等价的,const自带静态光圈。
const和readonly的本质区别如下:
注意:在构造方法中,readonly可以赋值多次。 也就是在初始化的时候。
7.使用0作为枚举的默认值
允许的枚举类型是 byte、sbyte、short、ushort、int、uint、long 和 ulong。 值 0 应始终用作枚举类型的默认值。 不过,这并不是因为允许的枚举类型在声明时默认值为0,而是具有工程意义。
由于枚举类型是从0开始的,这样可以避免一周多一个0值。
8.避免为枚举类型的元素提供显式的值
不要给枚举赋值。 有时需要向枚举中添加元素。 这时候就像我们在枚举中添加元素ValueTemp一样,很可能会不小心添加了一个无效的值。
9. 习惯重载运算符
例如:薪水familyIncome=mikeIncome+roseIncome; 一目了然。 通过使用 operator 关键字定义静态成员函数来重载运算符,使开发人员可以像使用内置原始类型一样使用该类型。
10、创建对象时,需要考虑是否实现比较器
有特殊需要比较时再考虑。 集合排序比较也可以通过linq来解决。
11. 区别对待==和Equals
运算符“==”和方法“Equals”都倾向于表达这样一个原则:
注意
12.重写Equals时,也重写GetHashCode
除非考虑自定义类型将作为基于散列的集合的键值; 否则不建议重写Equals方法,因为这会带来一系列的问题。
集合找值的时候本质上是先找HashCodec#字段和属性区别,再找对象比较Equals
注意:重写Equals方法时,还应该实现一个类型安全的接口IEquatable<T>,例如:class Person:IEquatable
13. 输出类型的格式化字符串
有两种方法可以为类型提供格式化的字符串输出。
典型的格式化程序应该继承接口 IFormatProvider 和 ICustomFomatter
14.正确实现浅拷贝和深拷贝
浅拷贝
将一个对象的所有字段复制到一个新对象中(副本)。 其中,值类型字段的值复制到副本后,副本中的修改不会影响源对象对应的值。 但是,引用类型的字段被复制到引用类型的引用的副本,而不是被引用的对象。 修改副本中引用类型字段的值会影响源对象本身。
深拷贝
同样,对象中的所有字段都被复制到新对象中。 但是无论是对象的值类型字段还是引用类型字段,都会重新创建并赋值,副本的修改不会影响到源对象本身。
无论是浅拷贝还是深拷贝,微软都建议类型继承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类型是引用类型,但是由于引用类型的特殊性(无论是实现上还是语义上),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方法c#字段和属性区别,如果我们想在一个类中同时实现深拷贝和浅拷贝,只能自己实现另外两个方法,声明为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;
}}
15.使用dynamic简化反射实现
动态是 Framework 4.0 的新特性。 dynamic的出现使得C#具有了弱语言类型的特点。 编译器在编译时不再检查类型,编译器默认动态对象支持开发者想要的任何特性。
例如,即使你对GetDynamicObject方法返回的对象一无所知,你也可以这样调用代码,编译器不会报错:
dynamic dynamicObject=GetDynamicObject();
Console.WriteLine(dynamicObject.Name);
Console.WriteLine(dynamicObject.SampleMethod());
当然,如果运行时dynamicObject不包含指定的特征(比如上面有返回值的方法SampleMethod),运行时程序会抛出RuntimeBinderException: "System.Dynamic.ExpandoObject" does not contain the definition of "SampleMethod" .
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后,代码看上去更简洁了,
并且在可控的范围内减少了一次拆箱的机会。
经验证,频繁使用的时候,消耗时间更少
建议:始终使用动态来简化反射实现。
总结
在大多数应用案例中,“效率”并没有那么高的地位,灵活性更为重要。 在某些情况下,“灵活性”并没有那么高的地位,效率才是最重要的。