zoukankan      html  css  js  c++  java
  • 读改善c#代码157个建议:建议13~15

    目录:

    • 建议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 = 0; return formatter.Deserialize(ms) as Product; } } } [Serializable] internal class NumberFlag { public string Num { get; set; } }

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

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

    运行:

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

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

    运行:

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

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

  • 相关阅读:
    request Dispatch
    xmlHTTPRequest
    java 文件上传
    文件上传(2)
    文件上传
    Tomcat 加入windows 服务自启动设置
    windows下配置两个或多个Tomcat启动的方法
    HibernateProxy异常处理 java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: org.hibernate.proxy.HibernateProxy. Forgot to register a type adapter?
    checkbox遍历操作, 提交所有选中项的值
    tomcat结合nginx使用 基础教程
  • 原文地址:https://www.cnblogs.com/sunchong/p/4663276.html
Copyright © 2011-2022 走看看