operator 关键字

operator 关键字用来重载内置运算符,或提供类/结构声明中的用户定义转换。它可以定义不同类型之间采用何种转化方式和转化的结果。

operator用于定义类型转化时可采用2种方式,隐式转换(implicit)和显示转换(explicit)

public class OperatorTestDemo
{
public static void Test()
{
OperatorTest mc = 1;//通过隐式装换,生成myclass对象
Console.WriteLine(mc.Value); OperatorTest mc2 = new OperatorTest(2);
Console.WriteLine((int)mc2);//显示转化,调用myclass至int的处理方法
Console.WriteLine(mc2);//隐式转化,调用myclass至string的处理方法
}
}
public class OperatorTest
{
private int value;//声明value私有字段
public int Value//声明只读属性
{
get { return value; }
}
public OperatorTest(int value)//构造函数
{
this.value = value;
} public static implicit operator OperatorTest(int value)//隐式声明的int转OperatorTest类处理方法
{
return new OperatorTest(value);
}
public static explicit operator int(OperatorTest mc)//显示声明的OperatorTest转int类处理方法
{
return mc.value;
}
public static implicit operator string(OperatorTest mc)//隐式声明的OperatorTest转string类处理方法
{
return ("定义的OperatorTest类string类型转化结果");
}
}

在利用implicit的隐式声明时,如果同时存在多个由当前类转化为其他类型数据的隐式声明的时候,可能出现2者都可以调用,编译器不知道选择哪个而出现的错误。

TypeConverter

[TypeConverter(typeof(StringToHumanTypeConverter))]
public class Human
{
public string Name { get; set; } public Human Child { get; set; }
} public class StringToHumanTypeConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
else
return base.CanConvertFrom(context, sourceType);
} public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
{
Human h = new Human();
h.Name = value as string;
return h;
} return base.ConvertFrom(context, culture, value);
} public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
Human h = (Human)value;
return $"Human.Name:{(h.Name)}";
}
return base.ConvertTo(context, culture, value, destinationType);
}
} public static void Test()
{
TypeConverter homanTypeConverter = TypeDescriptor.GetConverter(typeof(Human));
if (homanTypeConverter.CanConvertFrom(typeof(string)))
{
Human h = (Human)homanTypeConverter.ConvertFrom("ssd");
Console.WriteLine(h.Name);
}
if (homanTypeConverter.CanConvertTo(typeof(string)))
{
Human h = new Human() { Name= "张飞"};
Console.WriteLine(homanTypeConverter.ConvertTo(h, typeof(string)));
}
}

格式化字符串

string 中定义的两个静态重载方法string.Format。

var msg = string.Format("Hello Cnblogs, I am {0},Today is {1:yyyy-MM-dd} {2}."
, "张飞", DateTime.Now, DateTime.Now.DayOfWeek);
  1. string.Format方法中的不定参数args是一个数组,而format参数中的形如{0},{1}中的序号则是数组中对应的索引,所以最大序号必须小于参数个数(因为数组不能越界)。

  2. {}是微软定义好的标记,用于分割format字符串。如果需要在字符串中包含大括号的话就必须进行转义,这个转义也和我们平时使用的"/"转义表示法不同,需要使用两个大括号进行转义如 {{ 或者 }},类似于逐字前缀字符@修饰的字符串中双引号的表示。

     var msg2 = string.Format("Hello {{}},I am {0}", "张飞");
    var msg3 = @"张飞""";
  3. string.Format方法内部通过StringBuilder实现字符串的拼接。

  4. 形如"{ N [, M ][: formatString ]}"的格式化表示中:

    1. N是从0开始的整数,表示要格式化的参数的个数
    2. M是一个可选的整数,表示格式化后的参数所占的宽度,如果M是负数,那么格式化后的值就是左对齐的,如果M是正数,那么格式化后的值是右对齐的
    3. formatString为是另外一个可选的参数,表示格式代码

数字的格式化

标准格式化标识符

数学格式化为字符串时,格式代码通常是象‘X0’这样的格式。X是格式化标识符,0是精度标识符。格式标识符号共有9种,它们代表了大多数常用的数字格式。

字母 含义
C或c Currency 货币格式
D或d Decimal 十进制格式(十进制整数,不要和.Net的Decimal数据类型混淆了)
E或e Exponent 指数格式
F或f Fixed point 固定精度格式
G或g General 常用格式
N或n 用逗号分割千位的数字,比如1234将会被变成1,234
P或p Percentage 百分符号格式
R或r Round-trip 圆整(只用于浮点数)保证一个数字被转化成字符串以后可以再被转回成同样的数字
X或x Hex 16进制格式

图形化格式字符串

如果标准格式化标识符还不能满足需求。可以使用图形化格式字符串来创建定制的字符串输出。

图形化格式化使用占位符来表示最小位数,最大位数,定位符号,负号的外观以及其它数字符号的外观。

符号 名称 含义
0 0占位符 用0填充不足的位数
# 数字占位符 用#代替实际的位数
. 十进制小数点
, 千位分隔符 用逗号进行千位分割,比如把1000分割成1,000
% 百分符号 显示一个百分标识
E+0,E-0,e+0,e-0 指数符号 用指数符号格式化输出
\ 专一字符 用于传统格式的格式化序列,比如"\n"(新行)
'ABC',"ABC" 常量字符串 显示单引号或者双引号里面的字符串
; 区域分隔符 如果数字会被格式化成整数,负数,或者0,用;来进行分隔
,. 缩放符号 数字除以1000

数字字符串的解析

string t = "  -1,234,567.890  ";
double g1 = double.Parse(t);
Console.WriteLine("g1 = {0:F}", g1); //g1 = -1234567.89 //使用NumberStyles
double g2 = double.Parse(t,
NumberStyles.AllowLeadingSign |
NumberStyles.AllowDecimalPoint |
NumberStyles.AllowThousands |
NumberStyles.AllowLeadingWhite |
NumberStyles.AllowTrailingWhite);
Console.WriteLine("g2 = {0:F}", g2); //g2 = -1234567.89 //通过NumberFormatInfo的CurrencySymbol属性,兼容货币符号
string u = "¥ -1,234,567.890 ";
NumberFormatInfo ni = new NumberFormatInfo();
ni.CurrencySymbol = "¥";
double d = Double.Parse(u, NumberStyles.Any, ni);
Console.WriteLine("d = {0:F}", d); //h = -1234567.89 //通过CultureInfo,执行特定文化的操作
int k = 12345;
CultureInfo us = new CultureInfo("en-US");
string v = k.ToString("c", us);
Console.WriteLine(v); //$12,345.00 CultureInfo dk = new CultureInfo("da-DK");
string w = k.ToString("c", dk);
Console.WriteLine(w); //kr 12.345,00

日期的格式化

字母 格式 含义
d MM/dd/yyyy ShortDatePattern(短日期模式)
D dddd,MMMM dd,yyyy LongDatePattern(长日期模式)
f dddd,MMMM dd,yyyy HH:mm Full date and time (long date and short time)(全日期和时间模式)
F dddd,MMMM dd,yyyy HH:mm:ss FullDateTimePattern (long date and long time)(长日期和长时间)
g MM/dd/yyyy HH:mm General (short date and short time)(通用模式,短日期和短时间)
G MM/dd/yyyy HH:mm:ss General (short date and long time)(通用模式,短日期和长时间)
m,M MMMM dd MonthDayPattern(月天模式)
r,R ddd,dd MMM yyyy,HH':'mm':'ss 'GMT' RFC1123Pattern (RFC1123模式)
S yyyy-MM-dd HH:mm:ss SortableDateTimePattern (conforms to ISO 8601) using local time(使用本地时间的可排序模式)
t HH:mm ShortTimePattern (短时间模式)
T HH:mm:ss LongTimePattern(长时间模式)
u yyyy-MM-dd HH:mm:ss UniversalSortable-DateTimePattern (conforms to ISO 8601) using universal time(通用可排序模式)
U dddd,MMMM dd,yyyy,HH:mm:ss UniversalSortable-DateTimePattern(通用可排序模式)
y,Y MMMM,yyyy YearMonthPattern(年月模式)
DateTimeFormatInfo dtfi;
Console.Write("[I]nvariant or [C]urrent Info?: ");
if (Console.Read() == 'I')
dtfi = DateTimeFormatInfo.InvariantInfo;
else
dtfi = DateTimeFormatInfo.CurrentInfo;
DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToString("D", dtfi));
Console.WriteLine(dt.ToString("f", dtfi));
Console.WriteLine(dt.ToString("F", dtfi));
Console.WriteLine(dt.ToString("g", dtfi));
Console.WriteLine(dt.ToString("G", dtfi));
Console.WriteLine(dt.ToString("m", dtfi));
Console.WriteLine(dt.ToString("r", dtfi));
Console.WriteLine(dt.ToString("s", dtfi));
Console.WriteLine(dt.ToString("t", dtfi));
Console.WriteLine(dt.ToString("T", dtfi));
Console.WriteLine(dt.ToString("u", dtfi));
Console.WriteLine(dt.ToString("U", dtfi));
Console.WriteLine(dt.ToString("d", dtfi));
Console.WriteLine(dt.ToString("y", dtfi));
Console.WriteLine(dt.ToString("dd-MMM-yy", dtfi));

通过IFormatProvider,ICustomFormatter,IFormattable自定义格式化标识

string.Format("{0}+{1}={2}",a,b,a+b)的执行中,变量a、b、及计算结果(a+b)会自动调用.ToString()方法。

而在string.Format("d = {0:F}", d)这样带格式化标识的式子中变量d则是是通过 IFormattable 接口 调用方法 string ToString(string format,IFormatProvider formatProvider)

接口定义

//     提供用于检索控制格式化的对象的机制。
[ComVisible(true)]
public interface IFormatProvider
{
// 返回一个对象,该对象为指定类型提供格式设置服务。
object GetFormat(Type formatType);
} // 定义一种方法,它支持自定义设置对象的值的格式。
[ComVisible(true)]
public interface ICustomFormatter
{
// 使用指定的格式和区域性特定格式设置信息将指定对象的值转换为等效的字符串表示形式。
string Format(string format, object arg, IFormatProvider formatProvider);
} // 提供将对象的值格式化为字符串表示形式的功能。
[ComVisible(true)]
public interface IFormattable
{
string ToString(string format, IFormatProvider formatProvider);
}

简单实现

IFormattable

public class Greeting : IFormattable
{
private string name;
public Greeting(string name)
{
this.name = name;
}
public override string ToString()
{
return this.ToString("CN",null);
} public string ToString(string format, IFormatProvider provider)
{
if (string.IsNullOrEmpty(format))
return this.ToString();
if (provider == null)
provider = CultureInfo.CurrentCulture;
switch (format.ToUpper())
{
case "CN":
case "TW":
return "你好," + name.ToString();
case "US":
case "GB":
return "Hello," + name.ToString();
case "JP":
return "こんにちは," + name.ToString();
default:
throw new FormatException(string.Format("The {0} format string is not supported.", format));
}
}
} Greeting greeting = new Greeting("张飞"); Console.WriteLine(string.Format("{0}", greeting));
Console.WriteLine(string.Format("{0:US}", greeting));
Console.WriteLine(string.Format("{0:JP}", greeting)); Console.WriteLine(greeting.ToString("CN", CultureInfo.CurrentCulture));
Console.WriteLine(greeting.ToString("US", CultureInfo.CurrentCulture));
Console.WriteLine(greeting.ToString("JP", CultureInfo.CurrentCulture));

IFormatProvider,ICustomFormatter

通过IFormatProvider来实现自定义格式化参数,相对于IFormattable接口来说更加灵活,因为不必为每个类单独去实现IFormattable接口。

public class MyFormater : ICustomFormatter, IFormatProvider
{
public object GetFormat(Type format)
{
if (format == typeof(ICustomFormatter))
return this;
return null;
} 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 == "MyFormater")
{
return "£:" + arg.ToString();
}
else
{
if (arg is IFormattable)
return ((IFormattable)arg).ToString(format, provider);
return arg.ToString();
}
}
}
} public static void Test()
{
int i = 100;
string printString;
MyFormater myFormater = new MyFormater();
printString = string.Format(myFormater, "{0}", i);
Console.WriteLine(printString);
printString = string.Format(myFormater, "{0:C}", i);
Console.WriteLine(printString);
printString = string.Format(myFormater, "{0:MyFormater}", i);
Console.WriteLine(printString);
}

总结

通过String Format(IFormatProvider provider, String format, params object[] args)方法才能使用自定义的格式化标识

Console.WriteLine(string.Format(myFormater, "{0:MyFormater}", 100)); //£.100
Console.WriteLine(100.ToString("MyFormater", new MyFormater())); //100 Console.WriteLine(string.Format(DateTimeFormatInfo.InvariantInfo, "{0:yy-MM-dd}", DateTime.Parse("2016.12.21"))); //16-12-21
Console.WriteLine(string.Format("{0:yy-MM-dd}", DateTime.Parse("2016.12.21"))); //16-12-21
Console.WriteLine(DateTime.Parse("2016.12.21").ToString("yy-MM-dd", DateTimeFormatInfo.InvariantInfo));//16-12-21

IConvertible

//     定义特定的方法,这些方法将实现引用或值类型的值转换为具有等效值的公共语言运行时类型。
[CLSCompliant(false)]
[ComVisible(true)]
public interface IConvertible
{
// 枚举常数,它是实现该接口的类或值类型的 System.TypeCode。
TypeCode GetTypeCode(); bool ToBoolean(IFormatProvider provider);
byte ToByte(IFormatProvider provider);
char ToChar(IFormatProvider provider);
DateTime ToDateTime(IFormatProvider provider);
decimal ToDecimal(IFormatProvider provider);
double ToDouble(IFormatProvider provider);
short ToInt16(IFormatProvider provider);
int ToInt32(IFormatProvider provider);
long ToInt64(IFormatProvider provider);
sbyte ToSByte(IFormatProvider provider);
float ToSingle(IFormatProvider provider);
string ToString(IFormatProvider provider);
object ToType(Type conversionType, IFormatProvider provider);
ushort ToUInt16(IFormatProvider provider);
uint ToUInt32(IFormatProvider provider);
ulong ToUInt64(IFormatProvider provider);
}

类型转换扩展方法

/// <summary>
/// 提供类型转换
/// </summary>
/// <typeparam name="T">要得到的类型(可以是可选类型)</typeparam>
/// <param name="obj"></param>
/// <param name="convertTo">可以主动提供一个TypeConverter类型,会自动调用它的CanConvertTo和ConvertTo方法</param>
/// <param name="format">格式化标识符</param>
/// <param name="formatProvider">格式化提供器</param>
/// <returns>转换结果</returns>
public static T ConvertTo<T>(this object obj, TypeConverter convertTo = null,string format = null, IFormatProvider formatProvider = null)
{
if (obj == null)
{
return default(T);
} Type targetType = typeof(T); //可选类型
if (targetType.IsNullableType())
{
targetType = targetType.GetUnderlyingType();
}
//枚举
if (targetType.IsEnum)
{
return (T)Enum.Parse(targetType, obj.ToString());
}
//guid
if (targetType == typeof(Guid))
{
object o = Guid.Parse(obj.ToString());
return (T)o;
}
//TypeConverter
if (convertTo != null)
{
if (convertTo.CanConvertTo(targetType))
return (T)convertTo.ConvertTo(obj, targetType);
}
//自定义字符串格式化
if(targetType == typeof(string) && format != null&& formatProvider != null)
{
object result = string.Format(formatProvider, "{0:" + format + "}", obj);
return (T)result;
} //没有明确指定的转换方式,依次尝试各种可能的方式 Type from = obj.GetType();
convertTo = TypeDescriptor.GetConverter(from);
if (convertTo != null && convertTo.CanConvertTo(targetType))
{
return (T)convertTo.ConvertTo(obj, targetType);
}
TypeConverter convertFrom = TypeDescriptor.GetConverter(targetType);
if (convertFrom != null && convertFrom.CanConvertFrom(from))
{
return (T)convertFrom.ConvertFrom(obj);
} if (formatProvider == null)
{
formatProvider = CultureInfo.InvariantCulture;
}
if (targetType == typeof(string) && format != null)
{
object result = string.Format(formatProvider, "{0:"+ format + "}", obj);
return (T)result;
}
return (T)Convert.ChangeType(obj, targetType, formatProvider);
}

C#定义类型转化 及 格式化字符串的更多相关文章

  1. Date日期类型转化成中文字符串

    例子: select to_char(sysdate,'yyyy"年"mm"月"dd"日"') as nowYear from dual 结 ...

  2. 编写高质量代码改善C#程序的157个建议[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]

    前言 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html .本文主要学习记录以下内容: 建议13.为类型输出格式化字符串 建议14.正确实现浅拷贝和深 ...

  3. C#程序编写高质量代码改善的157个建议【13-15】[为类型输出格式化字符串、实现浅拷贝和深拷贝、用dynamic来优化反射]

    前言 本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html .本文主要学习记录以下内容: 建议13.为类型输出格式化字符串 建议14.正确实现浅拷贝和深 ...

  4. 编写高质量代码改善C#程序的157个建议——建议13: 为类型输出格式化字符串

    建议13: 为类型输出格式化字符串 有两种方法可以为类型提供格式化的字符串输出.一种是意识到类型会产生格式化字符串输出,于是让类型继承接口IFormattable.这对类型来 说,是一种主动实现的方式 ...

  5. struts2---自定义类型转换器

    从servlet我们知道从页面获取到的参数都是string类型,但是struts2中基本的数据类型,它可以自动帮我们转化为其对应的包装类,就像获取到123,可以自动转化为Integer,但是比如201 ...

  6. Python03 字符串类型、强制类型转化、列表、元组、字典、集合

    1 字符串类型 在python中字符串类型用str表示,字符串的连接用 + 1.1 创建字符串对象 ·创建一个字符串对象有两种方式,一种方式是直接用字符串进行赋值,另外一种是利用str类实例化对象:具 ...

  7. python_05 可变类型与不可变类型、集合、字符串格式化

    可变数据类型与不可变数据类型: 1.可变:列表,字典 2.不可变:字符串,数字,元组 访问顺序: 1.顺序访问:字符串,列表,元组 2.映射:字典 集合 由不同元素组成的集合,集合中是一组无序排列的可 ...

  8. js把其他类型转化成字符串

    js把其他类型转化成字符串 一.总结 一句话总结:类型转换中的强制类型转换分为类型转换函数和类型名强制.js后一种和其它语言不同,是类型类的构造方法.String() 二.js把其他类型转化成字符串 ...

  9. 040_字符串连接符 041_条件运算符目 042_运算符优先级_逻辑与或优先问题 043_自动类型转化 044_强制类型转换 045_基本类型常见错误_溢出_L问题

    040_字符串连接符 package test_package; /** * 字符串运算符 * @author * */public class TestOperator05 { public sta ...

随机推荐

  1. python之最强王者(2)——python基础语法

    背景介绍:由于本人一直做java开发,也是从txt开始写hello,world,使用javac命令编译,一直到使用myeclipse,其中的道理和辛酸都懂(请容许我擦干眼角的泪水),所以对于pytho ...

  2. php静态缓存简单制作

    制作缓存的目的是为了让我们的页面运行更加快速,减少读取数据库内容的次数,给用户更好的体验,为此我们可以使自己的程序做一下缓存,并且设置一个缓存过期的时间,来保证与数据库的一致,当然并不是所有的程序都适 ...

  3. js picker webapp仿ios picker

    iosselect 在webapp下的一个picker组件 可以轻松实现各类选择器效果.比如地区选择 时间选择 日期选择等. 可以定制依赖关系,可以定制选择层级,可以定制高度 展示项数.无论你是px还 ...

  4. Using AlloyTouch to control three.js 3D model

    As you can see, the above cube rotation, acceleration, deceleration stop all through the AlloyTouch ...

  5. DOM对象与jQuery对象的相互转换

    DOM  对象可以使用 js       中的方法,  不能使用jQuery中的方法:jQuery对象只能使用jQuery中的方法, 不能使用js中的方法:jQuery对象是通过jQuery包装DOM ...

  6. IOS-小项目(饿了么 网络部分 简单实现)

    在介绍小项目之前,在此说明一下此代码并非本人所写,我只是随笔的整理者. 在介绍之前先展现一下效果图. 看过效果图大家应该很熟悉了,就是饿了么的一个界面而已,值得注意的是,实现时并没有采用本地连接,而是 ...

  7. Mac 开发者常用的工具

    转载:http://www.oschina.net/news/53946/mac-dev-tools 在写 Mac 程序员的十个武器之前,我决定先讲一个故事,关于 Mac 和爱情的.(你们不是问 Ma ...

  8. Spring、hibernate以及struts2三大框架的整合

    1.首先导入整合框架所需要的43个jar包: 2.配置xml文件: <?xml version="1.0" encoding="UTF-8"?> & ...

  9. SQLServer中Partition By 函数的使用

    今天群里看到一个问题,在这里概述下:查询出不同分类下的最新记录.一看这不是很简单的么,要分类那就用Group By;要最新记录就用Order By呗.然后在自己的表中试着做出来: 首先呢我把表中的数据 ...

  10. MySQL多实例安装

    1.安装MySQL需要的依赖的包和编译软件   (1)安装MySQL需要的依赖包 安装MySQL之前,最好先安装MySQL需要的依赖包,不然后面会出现报错,还得回来安装MySQL的依赖包. [root ...