zoukankan      html  css  js  c++  java
  • 自定义格式字符串随笔(IFormattable,IFormatProvider,ICustomFormatter三接口的实现)

    .NET Framework提供了方法,能够将任何数值、枚举以及日期和时间等基数据类型表示为字符串
    格式化由格式说明符字符的字符串控制,该字符串指示如何表示基类型值
    例如,格式说明符指示:是否应该用科学记数法来表示格式化的数字
    例如:格式字符"C",说明货币格式

    同时.NET Framework还使用区域性设置,以便用适合于特定区域性的形式表示基类型。
    我们可以提供自定义的区域性设置,或者使用与当前线程关联的默认区域性设置。
    例如,格式化货币类型的时候,区域性设置指定用于货币符号

    要是我们想拥有自己定义的格式化,.NET Framework也允许我们定义自己格式化方案和自定义区域性设置。
    例如:我想格式字符"MyFormat",来说明我自定义的格式,即在字符前加三个***

    关于数字格式字符串,可以参考类
    System.Globalization.NumberFormatInfo
    关于日期与时间格式字符串,可以参考类
    System.Globalization.DateTimeFormatInfo

    先看看IFormattable接口的原型
    public interface IFormattable
    {
          // Methods
          string ToString(string format, IFormatProvider formatProvider);
    }
    参数说明:
    format
    指定要使用的格式的 String
    当为空引用时,表示使用为 IFormattable 实现的类型定义的默认格式
    formatProvider
    用于格式化该值的 IFormatProvider
    当为空引用时,从操作系统的当前区域设置中获取格式信息的

    一些基本的值类型实现了该接口,例如:
    Int32 ,UInt32 , DateTime ,Guid ,类Enum

    再看看IFormatProvider接口的原型
    public interface IFormatProvider
    {
          // Methods
          object GetFormat(Type formatType);
    }
    参数说明:
    formatType
    一个对象,它指定要获取的格式对象的类型

    NumberFormatInfo、DateTimeFormatInfo和CultureInfo实现IFormatProvider接口

    NumberFormatInfo提供数字格式信息,如用于小数分隔符和千位分隔符的字符,以及货币值中货币符号的拼写和位置
    DateTimeFormatInfo提供与日期相关和与时间相关的格式信息,如日期模式中月、日和年的位置
    CultureInfo包含特定区域性中的默认格式信息,其中包括数字格式信息以及与日期相关和与时间相关的格式信息

    再看看ICustomFormatter接口的原型
    public interface ICustomFormatter
    {
          // Methods
          string Format(string format, object arg, IFormatProvider formatProvider);
    }
    参数说明:
    format
    包含格式规范的格式字符串
    arg
    要格式化的对象
    formatProvider
    一个 IFormatProvider 对象,它提供有关当前实例的格式信息


    在arg为空引用时,引发异常
    如果 format 为空引用 ,将使用默认格式规范
    如果 formatProvider 为空引用 ,则忽略该参数

    好了,说了这么多
    我们来动手来实现格式字符"MyFormat",在字符前加三个***的需求

    定义一个类

    using System;

    namespace MyFormat
    {
        
    public class MyClass : System.IFormattable
        
    {
            Double d;

            
    public MyClass(Double d)
            
    {
                
    this.d=d;
            }


            
    public string ToString(string format, IFormatProvider formatProvider)
            
    {
                
    return (format=="MyFormat")?"***"+d.ToString(formatProvider):d.ToString(format,formatProvider);
            }

        }

    }

    再到一控制台中

    System.Globalization.CultureInfo culture=null;

                MyClass myClass
    =new MyClass(5);
                
    //当IFormatProvider为空时,调用的是当前线程关联的文化信息
                Console.WriteLine("显示中国货币格式:{0}",myClass.ToString("C",null));

                culture
    =System.Globalization.CultureInfo.CurrentCulture;
                Console.WriteLine(
    "显示当前系统默认货币格式:{0}",myClass.ToString("C",culture));

                culture
    =new System.Globalization.CultureInfo("zh-HK");
                Console.WriteLine(
    "显示香港特别行政区货币格式:{0}",myClass.ToString("C",culture));

                Console.WriteLine(
    "显示我自己定义的货币格式:{0}",myClass.ToString("MyFormat",null));
                
                Console.ReadLine();

    效果如下:


    如果希望自定义格式化能在多个不同类使用,那么实现我们应该实现ICustomFormatter接口

    定义一个类

    using System;

    namespace MyFormat
    {
        
    public class MyBaseFormat : System.ICustomFormatter, System.IFormatProvider
        
    {
            
    //如果format Type与当前实例类型相同,则为当前实例,否则为空引用
            public object GetFormat(Type format)
            
    {
                
    if (format == typeof (ICustomFormatter))
                    
    return this;
                
    return null;
            }


            
    //实现Format方法说明:
            
    //如果您的格式方法不支持格式,则确定正在设置格式的对象是否实现 IFormattable 接口。
            
    //如果实现,请调用该接口的IFormattable.ToString 方法。
            
    //否则,调用基础对象的默认 Object.ToString 方法。
            public string Format (string format, object arg, IFormatProvider provider)
            
    {
                
    if (format == null)
                
    {
                    
    if (arg is IFormattable)
                        
    return ((IFormattable)arg).ToString(format, provider);
                    
    return arg.ToString();
                }

                
    else
                
    {
                    
    if (format=="MyBaseFormat")  
                    
    {
                        
    return "***"+arg.ToString();
                    }

                    
    else
                    
    {
                        
    if (arg is IFormattable)
                            
    return ((IFormattable)arg).ToString(format, provider);
                        
    return arg.ToString();
                    }

                }

            }

        }

    }

    到一控制台中

                string printString=String.Empty;
                
    int i=100;
                MyBaseFormat myBaseFormat
    =new MyBaseFormat();

                printString
    =string.Format(myBaseFormat,"显示正常格式:{0}",i);
                Console.WriteLine(printString);
                printString
    =string.Format(myBaseFormat,"显示正常格式:{0:C}",i);
                Console.WriteLine(printString);
                printString
    =string.Format(myBaseFormat,"显示自定义格式{0:MyBaseFormat}",i);
                Console.WriteLine(printString);

                Console.ReadLine();

    效果如下:


    小总结:
    1.如果需要您自己的格式化包含在某个类上,在该类上实现IFormattable接口
    2.如果希望自定义格式化并使它可供多个不同类使用,那么实现 ICustomFormatter接口

  • 相关阅读:
    写一个通用的事件侦听器函数
    基于LuckySheet在线表格的Excel下载功能开发
    node项目中npm 第三方包引用规则
    js 本地保存 json/txt 文件
    letcood 算法题 -- 两数相加
    ES6新增语法总结
    关于Promise,你必须知道的几点。
    Promise 基础
    学习网页收藏
    android Listview每一个item添加点击事件
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2123078.html
Copyright © 2011-2022 走看看