C#如何提高代码质量(一)
代码部分 1.正确操作字符串 尽量少装箱 String str1 = "str2"+9.ToString(); 避免分配额外的内存空间 StringBuilder 2.使用默认转型方法 使用类型的转换运算符 编译器直接支持的数据类型,即直接映射到FCL中的类型。包括sbyte、byte、short、ushort、int、uint、long、ulong、char、float、double、bool、decimal、object、string 使用类型内置的方法 Parse,TryParse,ToString,ToDouble,ToDateTIme 使用帮助类提供的方法 System.Convert和System.BitConverter 使用CLR支持的转型 基类和子类的相互转换 3.区别对待强制转型与as和is 强转 继承public static explicit operator 类名(待转换类名) as 不抛出异常 4.TryParse比Parse好 5.使用int?来确保值类型也可以为null 6.区别readonly和const的使用方法 const是编译器常量(自带static),readonly是一个运行时常量 const只能修饰基元类型,枚举或者字符串,readonly没有限制 "readonly第一次被赋值后不可以改变 1.对于值类型,值本身不可改变 2.对于引用类型,引用本身(指针)不可改变" 7.将0值作为枚举的默认值 编译器会从0值开始计数 8.习惯重载运算符 9.创建对象时需要考虑是否实现比较器 实现Icompareable或Icomparer<T> 10.区别对待==和Equals "对于值类型,如果类型的值相等,就应该返回True对于应用类型,如果类型指向同一个对象,则返回True" 11.为类型输出格式化字符串 12.用dynamic简化反射实现 dynamic 类 x = new 类(); 13.元素数量可变的情况下不应使用数组 一维数组:newarr,ldelemldelmea, stelem 14.使用List<T>而不是用ArrayList List<T> SortedList<T> ConcurrentBag<T> Dictionary<Tkey,Tvalue> StortedDictionary<Tkey,Tvalue> ConcurrentDictionary<Tkey,Tvalue> HashSet<T> StortedSet<T> Queue<T> ConcurrentQueue<T> Stack<T> ConcurrentStack<T> 15.确保集合的线程安全 需要使用lock进行锁定 16.迭代器不要有可写属性 17.谨慎集合中的可写属性 18.使用匿名类型存储LINQ查询结果 var personWithCompanyList = from person in personList join company in companyList on person.CompanyID qeuals company.ComanyID select new {PersonName=person.Name, CompanyName = company.Name} 19.查询中受用Lambda表达式 20.延迟求值和主动求职的区别 from c in list where c>5 select c 延迟求值 (from c in list where c>5 select c).ToList<int>(); 主动求值 21.区别Linq查询中的Ienumerable<T>和Iqueryable<T> IEnumerable<T> 本地数据源 基本变量 IQueryable<T> 远程数据源 数据库 不能直接使用自定义方法 22.使用LINQ取代集合中的比较器和迭代器 23.使用Linq时注意不必要的迭代 (from c in list select c).Take(2).ToList() 只迭代两次 (from c in list where c.name=="Mike" select c).First() 拿到就返回 泛型/委托和事件 24.尽可能使用泛型 25.避免在泛型类型中声明静态成员 泛型中数据类型不一致,则静态成员不共享 26.为泛型参数设定约束 public int Compare<T>(T t1, T t2) where T:Salary 此时T变为了Salary类,就拥有了其相关属性 27.使用default为泛型类型变量指定初始值 28.使用FCL中的委托声明 Action,Func,Predicate 29.使用Lambda进行委托 Func<int, int, int> add = delegate(int I, int j){return i+j;}; Action<string> print = delegate(string msg){Console.WriteLine(msg);}; print(add(1,2).ToString()); Func<int, int, int> add =(I, j)=>{return i+j;}; Action<string> print = (msg)=>{Console.WriteLine(msg);}; 30.小心闭包中的陷阱 触发方法时才会调用方法 31.使用event关键字为委托施加保护 32.标准的事件模型 public delegae void EventHandler(object sender, EventArgs e); 委托类型的名称以EventHandler结束 委托原型返回值为void 委托原型有两个参数:sender表示事件触发者,e表示事件参数 事件参数的名称以EventArgs结束 33.为泛型类型参数指定逆变 资源管理和序列化 1.显示释放资源需集成接口Idisposable 2.必要时应将不再使用的对象引用赋值为null 静态变量不会主动Disposable 3.为无用字段标注不可序列化 [Serializable] 序列化 [NonSerialized] 不序列化 [fidle:NonSerialized] 事件非序列化 public class BinarySerializer{ //将类型序列化为字符串 public static string Serialize<T>(T t){ using(MemoryStream stream = new MemoryStream()){ BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, t); return System.Text.Encoding.UTF8.GetString(stream.ToArray()); } } // 将类型序列化为文件 public static void SerializeToFile<T>(T t, string path, string fullName){ if(!Directory.Exists(path)){Directory.CreateDirectory(path);} string fullPath = $""{pth}\{fullName}""; using(FileStream stream = new FileStream(fullPath, FileMode.OpenOrCreate)) { BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, t); stream.Flush(); } } //将字符串反序列化为类型 public static TResult Deserialize<TResult>(string s) where TResult:class{ byte[] bs = System.TextEncoding.UTF8.GetBytes(s); using (MemoryStream stream = new MemoryStream(bs)){ BinaryFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(stream) as TResult; } } //将文件反序列化为类型 public static TResult DeserializeFromFile<TResult>(string path) where TResult:class{ using(FileStream stream = new FileStream(path, FileMode.Open)){ BinaryFormatter formatter = new BinaryFormatter(); return formatter.Deserialize(stream) as TResult; } } } 4.利用定制特性减少可序列化的字段 OnDeserializedAttribute 指定对象反序列化后立即调用此方法 OnDeserializeingAttribute 指定在反序列化时调用此方法 OnSerializedAttribute 指定在序列化该对象后是否调用该方法 OnSerializingAttribute 指定在对象序列化前调用此方法 5.使用集成Iserializable接口更灵活的控制序列化过程