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;
}}

金蝶k3 单据字段 属性_c#字段和属性区别_类的属性和字段有什么不同

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后,代码看上去更简洁了,并且在可控的范围内减少了一次拆箱的机会。经验证,频繁使用的时候,消耗时间更少

建议:始终使用动态来简化反射实现。

总结

在大多数应用案例中,“效率”并没有那么高的地位,灵活性更为重要。 在某些情况下,“灵活性”并没有那么高的地位,效率才是最重要的。

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注