C#支持的运算符

https://msdn.microsoft.com/zh-cn/library/6a71f45d(v=vs.140).aspx

checked 和 unchecked

byte b = ;
b++;
Console.WriteLine(b);

byte数据类型 范围 0~255。递增 b 的值会导致溢出。CLR如何处理这个溢出取决于很多因素,包括编译器选项。

可以使用代码块标记 checked,发生溢出,抛出 OverflowException 异常。

byte b = ;
checked
{
b++;
}
Console.WriteLine(b);

也可以用  /checked  编译器选项进行编译,就可以检查程序中所有未标记代码中的溢出。

反之 unchecked 不检查溢出,注意 unchecked 是默认行为。

byte b = ;
unchecked
{
b++;
}
Console.WriteLine(b);

is运算符

检查对象是否是该该类型,或者派生自该类型。

 int value = ;
Console.WriteLine( (value is int) + " " + (value is object));

as 运算符

执行引用类型的显示类型转换。如果类型不兼容,返回null。

object str = "Hello";
object value = ;
string str1 = str as string;
string value2 = value as string;

value2 等于 null

sizeof运算符

确定在栈中值类型需要的字节大小。

Console.WriteLine( sizeof(int) );

如果是复杂类型(和非基本类型)使用sizeof运算符,需要放在 unsafe 代码块中。

unsafe
{
Console.WriteLine(sizeof(Customer));
}

typeof 运算符

返回表示特定类型的 System.Type 对象。如 typeof(string) 返回表示 System.String 类型的Type对象。

可空类型运算符

int? v1 = null;
int? a = v1 + ; // a = null

空合并运算符

int? v1 = null;
v1 = v1 ?? ;
Console.WriteLine(v1);

运算符优先级

一般情况避免利用运算符优先级来生成正确结果,用圆括号指定运算符执行顺序。

类型安全

中间语言(IL)对代码实现强制实现强类型。

强类型语言在没有强制类型转换前,不允许两种不同类型的变量相互操作。

类型转换

byte byte1 = ;
byte byte2 = ;
byte count = byte1 + byte2;
Console.WriteLine(count);

这里编译时,提示您 byte count 改成 int count。只是因为 两个 byte类型 相加 返回 int 类型,这时就需要类型转换了。

1、隐式转换

只要能保证值不会发生任何变化,类型转换就开自动(隐式)进行。

long count = byte1 + byte2;

2、显示转换类型

byte count =(byte) (byte1 + byte2);

要小心的时候显示转换类型,还要注意防止丢失数据。更不能转换 null 。

如果要 字符串 转换 为 int 时

string str = "";
int i = int.Parse(str);
str = i.ToString();

装箱和拆箱

装箱用于描述把一个值类型转换为引用类型。

拆箱把引用类型转换为值类型。

比较引用类型的相等性

ReferenceEquals

两个版本 Equals

比较运算符(==)

1、ReferenceEquals

ReferenceEquals是一个静态方法,测试两个引用类的同一个实例,判断两个引用是否包含内存中的相同地址。

2、虚函数 Equals

因为是虚函数,所以需要在类中重写它,比较。比较方式可以通过值。如果需要用类的实例用作字典中的键,那么需要重写 Object.GetHashCode() 的方式,注意此方式效率非常低的。

3、静态函数 Equals

有两个参数,如果两个引用实际上引用了某个对象,它就调用虚函数 Equals 实例方法。这表示重写了 虚函数 Equals ,也重写了静态版本函数。

4、比较运算符 ==

比较值和比较引用。

ReferenceEquals 用于比较引用,Equals 用于比较值,比较运算符看作一个中间项。ReferenceEquals应用值类型时,总是返回false。因为值类型需要装箱到对象中。

System.ValueType 提供的 Equals 的默认重写版本肯定足以应付绝大多数自定义的结构,但仍可以针对自己的接口再次重写它,以提供性能。

运算符重载

重载不仅仅限于算术运算符。还可以 重载比较运算符 ==、< 。等 语句 if(a==b) 默认比较引用,对于 string,比较字符串是否相同。

struct Vector
{
public double x, y, z; public Vector(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
} public Vector(Vector rhs)
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
} public override string ToString()
{
return x + " " + y + " " + z;
} public static Vector operator +(Vector lhs, Vector rhs)
{
Vector result = new Vector(lhs);
result.x += rhs.x;
result.y += rhs.y;
result.z += rhs.z;
return result;
} public static Vector operator *(Vector lhs, double rhs)
{
return new Vector(rhs * lhs.x, rhs * lhs.y, rhs * lhs.z);
}
}

一般运算符左边参数命名 lhs,运算符右边命名 rhs。

Vector vector1, vector2, vector3;
vector1 = new Vector(4.0, 3.0, 1.0);
vector2 = new Vector(4.0, -3.0, -1.0);
vector3 = vector1 + vector2;
Console.WriteLine(vector3);

与C++语言不同,C#不允许重载 "=" 运算符,但如果重载 "+" 运算符,编译器自动使用 "+" 运算符的重载执行 += 匀速符操作。

比较运算符重载

  • == 和 !=
  • > 和 <
  • >= 和 <=

如果重载了 "==",就必须重载 "!=" 。另外,比较运算符必须返回布尔类型的值。

重载 "==" 和 "!=" 时,必须重载 System.Object 中继承 Equals 和 GetHashCode 方法,否则会产生一个编译警告。原因是Equals方法实现与"=="运算符相同类型的相等逻辑。

public static bool operator ==(Vector lhs, Vector rhs)
{
if (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z)
{
return true;
}
else
{
return false;
}
} public static bool operator !=(Vector lhs, Vector rhs)
{
return !(lhs == rhs);
} public override bool Equals(object obj)
{
return base.Equals(obj);
} public override int GetHashCode()
{
return base.GetHashCode();
}

用户自定义的类型强制重载

c#允许定义自己的数据类型(结构和类),并可以在自定义数据类型之间进行类型强制转换。

public static implicit operator float(Currency value)
{
return (float) value;
}

这里定义的类型强制转换可以隐式地把Currency型的值转换为float型。

implicit 声明 数据类型转换为隐式的,编译器就可以隐式或显式的使用这个转换。

explicit 声明为显式的使用它。

public static explicit operator Celsius(Fahrenheit fahr)
{
return new Celsius((5.0f / 9.0f) * (fahr.degrees - ));
} Fahrenheit fahr = new Fahrenheit(100.0f);
Console.Write("{0} Fahrenheit", fahr.Degrees);
Celsius c = (Celsius)fahr;

类型强制转换必须同时声明为 public 和 static。

https://msdn.microsoft.com/zh-cn/library/xhbhezf4.aspx

C++中,类型强制转化针对于类的实例成员。

示例

     struct Currency
{
public uint Dollars;
public ushort Cents; public Currency(uint dollars, ushort cents)
{
this.Dollars = dollars;
this.Cents = cents;
} public override string ToString()
{
return string.Format("${0}.{1,-2:00}", Dollars,Cents);
} // 隐式转换
public static implicit operator float(Currency value)
{
return value.Dollars + (value.Cents / 100.0f);
} // 显示转换
public static explicit operator Currency(float value)
{
uint dollars = (uint)value;
ushort cents = (ushort)((value - dollars) * );
return new Currency(dollars, cents);
} } static void Main(string[] args)
{
try
{
Currency balance = new Currency(,); Console.WriteLine(balance); // 转换为 float
Console.WriteLine("balance is " + balance); // 隐式调用 toString
Console.WriteLine("balance is (using ToString()) " + balance.ToString()); // 显示调用 toString float balance2 = balance; // 隐式转为 float Console.WriteLine("After converting to float, = " + balance2); balance = (Currency) balance2; // 显示转为 Currency Console.WriteLine("After converting back to Currency, = " + balance);
Console.WriteLine("Now attempt to convert out of range value of " +
"-$50.50 to a Currency:"); checked
{
balance = (Currency)(-50.50); // 显示转为 Currency
Console.WriteLine("Result is " + balance.ToString());
}
}
catch(Exception e)
{
Console.WriteLine("Exception occurred: " + e.Message);
} Console.ReadLine();
}

类型转换的语法对于结构和类一样的。

类之间的类型强制转换

定义不同结构或类的实例之间的类型强制是完全合法,也有限制:

  • 如果某个类派生自另一个类,就不能定义这两个类之间的类型强制转换(因为这些类型转换已存在)。
  • 类型强制必须在源数据类型或目标数据类型的内部定义。

C#要求把类型强制转换的定义放在源类或目标类的内部。因为这样可以防止第三方类型强制转换引入类中。

基类和派生类之间的类型强制转换

MyBase 和 MyDerived。其中 Myderived 直接或间接派生自 MyBase 类。

MyDerived derivedObject = new MyDerived();
MyBase baseCopy = derivedObject;

MyDerived 隐式地强制转换为 MyBase

MyBase derivedObject = new MyDerived();
MyBase baseObject = new MyBase();
MyDerived derivedCopy1 = (MyDerived) derivedObject; // OK
MyDerived derivedCopy2 = (MyDerived) baseObject; // Throws exception

基类是不可以强制转为派生类。

装箱和拆箱数据类型强制转换

object derivedObject = new Currency();
object baseObject = new object();
Currency derivedCopy1 = (Currency) derivedObject; // OK
Currency derivedCopy2 = (Currency) baseObject; // Throws exception

多重类型转换

 Currency balance = new Currency();
long amount = (long) balance;
double amountD = balance;

Currency 定义了一个 float 的隐式转换,编译器又知道如何显式地从 float 强制转换为 long。所以 IL代码 首先把 balance 转换为 float,在把结果转换 long。类似这样。

long amount = (long) (double)balance;

最新文章

  1. CRL快速开发框架系列教程十一(大数据分库分表解决方案)
  2. RXJava by Example--转
  3. gradle和maven有什么用?分别有什么区别?
  4. HDU 1166 敌兵布阵(线段树单点更新)
  5. VMware Fusion DHCP方式下如何指定虚拟机IP地址
  6. linux增加自定义path和manpath
  7. mono的https使用使用事项
  8. Invalidate、RedrawWindow与UpdateWindow
  9. classLoader (一)
  10. mysql grant all privileges on
  11. CImage类
  12. java中instanceof的用法
  13. js基本语法汇总
  14. (62)Wangdao.com第十天_JavaScript 变量的作用域
  15. Visual Studio 2017 和 Visual Assist X 番茄助手的安装教程
  16. 从零基础到拿到网易Java实习offer,谈谈我的学习经验
  17. 吴恩达课后作业学习2-week1-2正则化
  18. Python中的iteritems()和items()
  19. hadoop 设置回收站
  20. Spring Boot application.yml bootstrap.yml

热门文章

  1. Node async 控制代码执行顺序
  2. 最新 易车java校招面经 (含整理过的面试题大全)
  3. bootstrap基础学习【菜单、按钮、导航】(四)
  4. Reactor系列(十一)take获取
  5. HBase的简单介绍,寻址过程,读写过程
  6. 使用Dreamweaver制作简单网站(二)
  7. 小菜鸟之SSM框架
  8. redis通用命令
  9. springboot+mybatis 用redis作二级缓存
  10. 数据结构:BF算法