目录:

  • 建议13:为类型输出格式化字符串
  • 建议14:正确实现浅拷贝和深拷贝
  • 建议15:使用dynamic来简化反射实现

一、建议13:为类型输出格式化字符串

有些类型需要我们根据业务需求提供字符串的格式化输出。

1、我们明确知道业务需求什么样的输出格式,也就是类型主动格式化输出。

可以重写Object.ToString()方法,也可以继承IFormattable接口实现ToString,对字符串进行输出。

class Person :IFormattable
{
public string IDCode { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; } public string ToString(string format, IFormatProvider formatProvider)
{
switch (format)
{
case "CH": return this.ToString();
case "US": return string.Format("{0}{1}", LastName, FirstName);
default: return this.ToString();
}
} public override string ToString()
{
return string.Format("{0}{1}", FirstName,LastName);
}
}

客户端:

 Person p = new Person() { IDCode = "No1", FirstName = "Sun", LastName = "N" };

            Console.WriteLine(p);

            Console.WriteLine(p.ToString("CH", null));
Console.WriteLine(p.ToString("US", null)); Console.ReadKey();

实例:记得之前做过一个API展示:API的Name是英文名,还有一个字段描述。现在我想看到API.ToString()展示的格式是:英文名:描述。就可以稍微重写ToString()进行格式化输出。

         public override string ToString()
{
if (!string.IsNullOrEmpty(this.ApiName) && !string.IsNullOrEmpty(this.Description))
return string.Format("{0}:{1}", this.ApiName, this.Description); return string.Empty;
}

2、使用格式化器进行格式化输出

如果类不能提供字符串的格式化输出,我们就可以使用格式化器,好处是我们可以根据需求修改格式化器的输出。

 class Person
{
public string IDCode { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}

格式化器:典型的格式化器应该继承IFormatProvider(继承这个接口有什么作用?), ICustomFormatter

class PersonFormatter : IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
else
return null;
} public string Format(string format, object arg, IFormatProvider formatProvider=null)
{
Person p = arg as Person;
if (p == null)
return string.Empty; switch (format)
{
case "CH": return string.Format("{0}{1}", p.FirstName, p.LastName);
case "US": return string.Format("{0}{1}", p.LastName, p.FirstName);
default: return string.Format("{0}{1}", p.FirstName, p.LastName);
}
}
}

客户端:

 Person p = new Person() { IDCode = "No1", FirstName = "Sun", LastName = "N" };

            //不重写ToString,返回类型名称
Console.WriteLine(p.ToString()); PersonFormatter pf = new PersonFormatter(); Console.WriteLine(pf.Format("CH", p)); Console.WriteLine(pf.Format("US", p)); Console.WriteLine(pf.Format("", p)); Console.ReadKey();

运行:

二、建议14:正确实现浅拷贝和深拷贝

建议继承ICloneable接口。浅拷贝,拷贝的对象中的引用类型的值的改变会互相影响。而深拷贝就是为了解决浅拷贝的这个问题。

下面是继承了ICloneable接口,并实现了浅拷贝和深拷贝的类。

这里的深拷贝的实现方法是使用序列化格式化器:BinaryFormatter,将类成员信息序列化成二进制流,然后反序列化成当前类。这里使用序列化所以类需要加上特性[Serializable],以示此类具有序列化、反序列化能力。

[Serializable]
internal class Product:ICloneable
{
public string Name { get; set; } public int Age { get; set; } public NumberFlag Number { get; set; }

     //浅拷贝
public object Clone()
{
return this.MemberwiseClone();
}
     //深拷贝
public Product DeepClone()
{
using (System.IO.Stream ms = new System.IO.MemoryStream())
{
System.Runtime.Serialization.IFormatter formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); formatter.Context = new System.Runtime.Serialization.StreamingContext(System.Runtime.Serialization.StreamingContextStates.Clone); formatter.Serialize(ms, this); ms.Position = ; return formatter.Deserialize(ms) as Product;
}
}
}
[Serializable]
internal class NumberFlag
{
public string Num { get; set; }
}

客户端:浅拷贝—引用类型值得改变会相互影响。

Product p1 = new Product()
{
Name = "",
Age = ,
Number = new NumberFlag() { Num=""}
}; var p2 = p1.Clone() as Product; if (p2 != null)
{ p2.Number.Num = ""; Console.WriteLine("p1 Number:{0}.",p1.Number.Num); Console.WriteLine("p2 Number:{0}.",p2.Number.Num); Console.ReadKey();
}

运行:

客户端:深拷贝—不会有浅拷贝的那种情况。

Product p1 = new Product()
{
Name = "",
Age = ,
Number = new NumberFlag() { Num=""}
}; var p2 = p1.DeepClone(); if (p2 != null)
{ p2.Number.Num = ""; Console.WriteLine("p1 Number:{0}.",p1.Number.Num); Console.WriteLine("p2 Number:{0}.",p2.Number.Num); Console.ReadKey();
}

运行:

 三、建议15:使用dynamic来简化反射实现

这个建议~虽然实例中性能比反射好,但是编译期间跳过验证。运行时才进行类型安全检查。待比较后,才能确定是否使用反射还是dynamic.

读改善c#代码157个建议:建议13~15的更多相关文章

  1. 读改善c#代码157个建议:建议4~6

    目录: 建议4:TryParse比Parse好 建议5:使用int?确保值类型也可以为null 建议6:区别 readonly 和 const 的用法 一.建议4:TryParse比Parse 好 T ...

  2. 读改善c#代码157个建议:建议10~12

    目录: 建议10:创建对象时需要考虑是否实现比较器 建议11:区别对待==与Equals 建议12:重写Equals时也要重写GetHashCode 一.建议10:创建对象时需要考虑是否实现比较器 比 ...

  3. 读改善c#代码157个建议:建议7~9

    目录: 建议7:将0值作为枚举的默认值 建议8:避免给枚举类型的元素提供显示的值 建议9:习惯运算符重载 一.建议7:将0值作为枚举的默认值 允许使用的枚举类型有:byte.sbyte.short.u ...

  4. 读改善c#代码157个建议:建议1~3

    目录: 建议一:正确操作字符串 建议二:使用默认转型方法 建议三:区别对待强制转型和as 建议一.正确操作字符串 1.确保尽量少的装箱 static void Main(string[] args) ...

  5. 编写高质量代码改善程序的157个建议:第87个建议之区分WPF和WinForm的线程模型

    今天有时间了,继续<编写高质量代码改善程序的157个建议>的阅读,当我阅读到建议87的时候,里面的一些代码示例和文中所说的不一致了,是不是我现在用的是NetFramework 4.0的缘故 ...

  6. 编写高质量代码改善java程序的151个建议——导航开篇

    2014-05-16 09:08 by Jeff Li 前言 系列文章:[传送门] 下个星期度过这几天的奋战,会抓紧java的进阶学习.听过一句话,大哥说过,你一个月前的代码去看下,慘不忍睹是吧.确实 ...

  7. 编写高质量代码:改善Java程序的151个建议 --[117~128]

    编写高质量代码:改善Java程序的151个建议 --[117~128] Thread 不推荐覆写start方法 先看下Thread源码: public synchronized void start( ...

  8. Github即将破百万的PDF:编写高质量代码改善JAVA程序的151个建议

    在通往"Java技术殿堂"的路上,本书将为你指点迷津!内容全部由Java编码的最佳 实践组成,从语法.程序设计和架构.工具和框架.编码风格和编程思想等五大方面,对 Java程序员遇 ...

  9. 每周一书-编写高质量代码:改善C程序代码的125个建议

    首先说明,本周活动有效时间为2016年8月28日到2016年9月4日.本周为大家送出的书是由机械工业出版社出版,马伟编著的<编写高质量代码:改善C程序代码的125个建议>. 编辑推荐 10 ...

随机推荐

  1. 学了Java 你未必知道这些

    作为一个正奔跑向编程完美天堂的朝圣者,本人觉得在平常的编程中,应该要做到以下几点: 一:汝应注释,这样做既方便别人,也方便自己去读懂代码的逻辑 二:注重细节,为自己写的每行代码负责,比如,在并发编程的 ...

  2. poj2348(博弈)

    poj2348 给定两个数a,b,大的数能减少小的数的倍数,不能是的数小于0,谁先使得数等于0,谁就赢了 有三种情况 ① a % b ==0  这个状态是必胜的 ② a - b < b  这个状 ...

  3. 简述负载均衡&CDN技术(转)

    曾经见到知乎上有人问“为什么像facebook这类的网站需要上千个工程师维护?”,下面的回答多种多样,但总结起来就是:一个高性能的web系统需要从无数个角度去考虑他,大到服务器的布局,小到软件中某个文 ...

  4. 用C设计,用C++编码

          昨天晚上看到刘江的blog又补充了好几大段,今天早上又看到云风的人肉trackback,果然还是这种话题引人关注. 云风先是提了一下所谓C++带来的思想包袱(文言文曰“心智包袱”)问题,然 ...

  5. Android:刚6瓶啤酒4两56度白酒下肚,竟然20分钟做了一手机版站点 !

    刚6瓶啤酒4两56度白酒下肚,竟然20分钟不到时间做了一手机版站点 !人有多大潜力你知道吗? 大家有兴趣的能够用手机或微信打开 http://xh.yunxunmi.com/  看看俺这酒后之做! 很 ...

  6. iOS开展-Xcode技巧总结(持续更新)

    1. <LLDB调试命令初探> 2. <Xcode LLDB Debug教程> 3. <iOS开发准备篇-(5)Xcode调试技巧_1> 4. <iOS开发准 ...

  7. mediator pattern

    20.4 中介者模式总结 中介者模式将一个网状的系统结构变成一个以中介者对象为中心的星形结构,在这个星型结构中,使用中介者对象与其他对象的一对多关系来取代原有对象之间的多对多关系.中介者模式在事件驱动 ...

  8. Web Socket rfc6455 握 (C++)

    std::string data((const char*)buf->data(),bytes_transferred); recycle_buffer(buf); std::string ke ...

  9. js+html+css简单的互动功能页面(2015知道几乎尖笔试题)http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html?from=y1.7-1.2

    js+html+css实现简单页面交互功能(2015知乎前端笔试题) http://v.youku.com/v_show/id_XMTI0ODQ5NTAyOA==.html? from=y1.7-1. ...

  10. [转]Qt 智能指针学习

    从内存泄露开始? 很简单的入门程序,应该比较熟悉吧 ^_^ #include <QApplication> #include <QLabel> int main(int arg ...