运算符和类型强制转换


1.运算符

运算符的简化操作

条件运算符:

if-else的简化操作,也称三元运算符。如果条件为真,返回一个值,为假返回另外一个值。

condition?true_value:false_value

checked和unchecked运算符:

如果把一个代码块标记为checked,CLR会执行溢出检查,如果溢出,会抛出OverflowException异常,运行以下代码会抛出异常。

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

如果要禁止溢出检查,将checked改为unchecked

unchecked是默认行为,只有在需要把几行未检查的代码放在一个显式地标记为checked的大代码块中,才需要显式使用unchecked

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

is运算符:

is运算符可以检查对象是否与特定的类型兼容。“兼容”表示对象是否该类型,或者派生自该类型

int i=;
if(i is object)
{
Console.WriteLine("i is an object");
}

as运算符:

as运算符执行引用类型的显式转换。如果转换的类型与指定的类型兼容,则转换成功,否则返回null

object o1="Some String";
object o2=; string s1=o1 as string;//s1="Some String"
string s2=o2 as string;//s2=null

sizeof运算符

使用sizeof运算符可以确定栈中值类型需要的长度(单位:字节)

Console.WriteLine(sizeof(int));

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

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

typeof运算符:

typeof运算符返回一个特定类型的Type对象,typeof(string)返回一个String类型的Type对象。

可空运算符?和运算符:

对于布尔类型,可以给它指定true或false值。但是要把该类型的值定义为undefined;这时候就可以使用可空类型,考虑null值和各种运算符一起使用的影响。

int? a= null;
int? b= a + ;//b=null
int? c = a * ;//c=null

空合并运算符??:

可以处理可空类型和引用类型时表示null可能的值。这个运算符放在两个操作数之间。第一个操作数必须是可空类型或引用类型。第二个操作数必须与第一个操作数类型相同,或者可以隐含地转换为第一个操作数的类型。空合并运算符的计算如下:
1.如果第一个操作数不是null,整个表达式就等于第一个操作数的值。
2.如果第一个操作数是null,整个表达式就等于第二个操作数的值。

如果a是null默认等于10;如果不是null;a就是3;

int? a = null;
int b; b = a ?? ;//b has the value 10
a = ;
b = a ?? ;//b has the value 3
运算符的优先级

3.类型的安全性

我们需要把一种类型转换为需要的另一种类型。

类型转换
byte value1 = ;
byte value2 = ;
byte total;
total = value1 + value2;
Console.WriteLine(total);

在试图编译这些代码时,会得到错误信息

Cannot implicitly convert type 'int' to 'type'

隐式转换:

只要值没有发生改变。类型转换就可以自动(隐式)进行

byte value1 = ;
byte value2 = ;
long total;
total = value1 + value2;
Console.WriteLine(total);

当2个byte类型相加时,实际上和的值已经变成long类型了,这时候不需要任何的类型强制转换。

C#支持的隐式类型转换

可空类型不能隐式的转换为非可空类型。必须通过显式转换。

不能进行显式转换的情况:

装箱和拆箱

装箱和拆箱是值类型和引用类型之间相互转换是要执行的操作。

1. 装箱在值类型向引用类型转换时发生

2. 拆箱在引用类型向值类型转换时发生

拆箱操作的执行过程和装箱操作过程正好相反,是将存储在堆上的引用类型值转换为值类型并给值类型变量。

int myIntNumber = ;
object myObject = myIntNumber;

int的基类是object类型,因为所有类型都继承自object类;子类转父类是隐式转换。父类转子类是显式转换。

object number = ;
int sum = (int)number + ;

4.比较对象的相等性

比较引用类型的相等性

RefernceEquals方法
RefernceEquals方法是一个静态方法,测试两个引用是否引用类的同一个实例。特别是两个引用是否包含内存中相同地址。方法不能重写。如果提供的两个引用是引用同一个对象实例。则返回true,否则返回false

SomeClass x, y;
x = new SomeClass();
y = new SomeClass();
bool B1 = ReferenceEquals(null, null);//true
bool B2 = ReferenceEquals(null, x);//false
bool B3 = ReferenceEquals(x, y);//true

虚拟的Equals方法

静态的Equals方法

比较运算符(==):

比较运算符只做值进行比较,不做引用比较。

比较值类型的相等性

5.运算符重载

您可以重定义或重载 C# 中内置的运算符。因此,程序员也可以使用用户自定义类型的运算符。重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。

例如,请看下面的函数:

public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}

上面的函数为用户自定义的类 Box 实现了加法运算符(+)。它把两个 Box 对象的属性相加,并返回相加后的 Box 对象。

运算符重载的实现

下面的程序演示了完整的实现:

using System;

namespace OperatorOvlApplication
{
class Box
{
private double length; // 长度
private double breadth; // 宽度
private double height; // 高度 public double getVolume()
{
return length * breadth * height;
}
public void setLength( double len )
{
length = len;
} public void setBreadth( double bre )
{
breadth = bre;
} public void setHeight( double hei )
{
height = hei;
}
// 重载 + 运算符来把两个 Box 对象相加
public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
} } class Tester
{
static void Main(string[] args)
{
Box Box1 = new Box(); // 声明 Box1,类型为 Box
Box Box2 = new Box(); // 声明 Box2,类型为 Box
Box Box3 = new Box(); // 声明 Box3,类型为 Box
double volume = 0.0; // 体积 // Box1 详述
Box1.setLength(6.0);
Box1.setBreadth(7.0);
Box1.setHeight(5.0); // Box2 详述
Box2.setLength(12.0);
Box2.setBreadth(13.0);
Box2.setHeight(10.0); // Box1 的体积
volume = Box1.getVolume();
Console.WriteLine("Box1 的体积: {0}", volume); // Box2 的体积
volume = Box2.getVolume();
Console.WriteLine("Box2 的体积: {0}", volume); // 把两个对象相加
Box3 = Box1 + Box2; // Box3 的体积
volume = Box3.getVolume();
Console.WriteLine("Box3 的体积: {0}", volume);
Console.ReadKey();
}
}
}

当上面的代码被编译和执行时,它会产生下列结果:

Box1 的体积:
Box2 的体积:
Box3 的体积:

下表描述了 C# 中运算符重载的能力:

6.用户定义的类型强制转换

实现用户定义的类型强制转换

在这个示例中,定义一个结构Currency,包含一个正的USD($)金额,C#为次提供了decimal类型,但如果需要进行复杂的财务处理。可以编写自己的结构和类来表示相应的金额。在这样的类上实现特定的方法。

struct Currency
{
public uint Dollars;
public ushort Cents; public Currency(uint dollars, ushort cents)
{
Dollars = dollars;
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.05f);
}
}
static void Main(string[] args)
{ Currency balance = new UnitTestProject1.Currency(, );
float f = balance;
}

如果将float类型给balance则不能进行转换。

float f = 10.5f;
Currency balance = new UnitTestProject1.Currency(, );
balance = f;

然后我们在Currency类再添加一个方法

public static explicit operator Currency(float value)
{
uint dollbars = (uint)value;
ushort cents = (ushort)((value-dollbars)*);
return new Currency(dollbars, cents);
}

下面代码会正常运行

Currency balance = new Currency(, ); Console.WriteLine(balance);
Console.WriteLine("balance is " + balance);
Console.WriteLine("balance is(using ToString()) " + balance.ToString());
float balance2 = balance;
Console.WriteLine("After converting to float,=" + balance2);
balance = (Currency)balance2;
Console.WriteLine("After converting back to Currency,=" + balance);
Console.WriteLine("Now attempt to convert out of range value of " + "-$50.50 to aCurrency:");
checked
{
balance = (Currency)(50.50);
Console.WriteLine("Result is " + balance.ToString());
}

类之间类型强制转换:

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

基类与派生类之间强制转换:

派生类实现了基类,基类转为派生类,这种情况是可以转换成功的

基类转派生类,这种情况是不能转换成功的。

MyBase derivedObject=new MyDerived();
MyBase baseObject=new MyBase();
MyDerived derivedCopy1=(MyDerived)derivedObject; //ok
MyDerived derivedCopy2=(MyDerived)baseObject;//Throws Exception

装箱与拆箱之间强制转换:

从基本类型到object类型是一种隐式的强制转换。因为这种强制转换是从派生类到基类的转换。

Currency balance=new Currency(,);
object baseCopy=balance;

对于基类的子类实现。由基类转换为子类。需要显示的强制转换。

object derivedObject=new Currency(,)
object baseObject=new object();
Currency derivedCopy1=(Currency)derivedObject;//ok
Currency derivedCopy2=(Currency)baseObject;//Exception
多重类型的强制转换

如果方法调用带有多个重载方法,并要给该方法传递参数。而该参数的数据类型不匹配任何重载方法,就可以迫使编译器确定使用哪些强制转换方式进行数据转换,从而决定使用哪个重载方法(并进行相应的数据转换)

C#高级编程9-第7章 运算符和类型强制转换的更多相关文章

  1. 【读书笔记】C#高级编程 第七章 运算符和类型强制转换

    (一)运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ -- 移位运算符 < ...

  2. C#高级编程 (第六版) 学习 第六章:运算符和类型强制转换

    第六章 运算符和类型强制转换 1,运算符 类别 运算符 算术运算符 + - * / % 逻辑运算符 & | ^ ~ && || ! 字符串连接运算符 + 增量和减量运算符 ++ ...

  3. C#学习笔记二 (资源托管,泛型,数组和元组,运算符和类型强制转换)

     托管和非托管资源 1.托管资源是指GC管理的内存空间,非托管资源是指文件句柄,网络连接,数据库连接等. 2.方法中临时申请的变量,被存放在栈中.栈存储非对象成员的值数据.例如在方法中有B b=new ...

  4. C#高级编程笔记 2016年10月8日运算符和类型强制转换

    1.checked和unchecked 运算符 C#提供了checked 和uncheckde 运算符.如果把一个代码块标记为checked, CLR就会执行溢出检查,如果发生溢出,就抛出overfl ...

  5. C# 运算符和类型强制转换(6) 持续更新

    C#支持的运算符 https://msdn.microsoft.com/zh-cn/library/6a71f45d(v=vs.140).aspx checked 和 unchecked ; b++; ...

  6. 读《C#高级编程》第1章问题

    读<C#高级编程>第1章 .Net机构体系笔记 网红的话:爸爸说我将来会是一个牛逼的程序员,因为我有一个梦,虽然脑壳笨但是做事情很能坚持. 本章主要是了解.Net的结构,都是一些概念,并没 ...

  7. C#高级编程9 第18章 部署

    C#高级编程9 第18章 部署 使用 XCopy 进行部署 本主题演示如何通过将应用程序文件从一台计算机复制到另一台计算机来部署应用程序. 1.将项目中生成的程序集复制到目标计算机,生成的程序集位于项 ...

  8. C#高级编程9 第17章 使用VS2013-C#特性

    C#高级编程9 第17章 使用VS2013 编辑定位到 如果默认勾选了这项,请去掉勾选,因为勾选之后解决方案的目录会根据当前文件选中. 可以设置项目并行生成数 版本控制软件设置 所有文本编辑器行号显示 ...

  9. C#高级编程9 第16章 错误和异常

    C#高级编程9 第16章 错误和异常 了解这章可以学会如何处理系统异常以及错误信息. System.Exception类是.NET运行库抛出的异常,可以继承它定义自己的异常类. try块代码包含的代码 ...

随机推荐

  1. python基础--类的方法

    一:类的方法说明 类的方法分为实例方法,析构方法,构造方法,类方法,静态方法,属性方法,等等 类方法和静态方法都可以被类和类实例调用,类实例方法仅可以被类实例调用 类方法的隐含调用参数是类,而类实例方 ...

  2. Spring MVC参数注入注意事项

    1.类参数名不能出现‘name’ 2.需提供默认的无参构造

  3. 神经网络中的激活函数tanh sigmoid RELU softplus softmatx

    所谓激活函数,就是在神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端.常见的激活函数包括Sigmoid.TanHyperbolic(tanh).ReLu. softplus以及softma ...

  4. caffe+win7+vs2013 仅CPU环境安装

    笔者对深度学习一直充满着好奇与兴趣,之前学校都是研究图像处理的特征点方式,机器学习使用也不多,别提深度学习了. 在看了李宏毅大佬的PPT后,有了初步的认识,虽然是渣渣电脑,也想自己跑几个深度模型. 说 ...

  5. 洛谷P1038神经网络

    传送门啦 一个拓扑排序的题,感觉题目好难懂... #include <iostream> #include <cstdio> #include <cstring> ...

  6. Python基础 - eazy_install和pip源设置

    在国内一般推荐豆瓣的源,虽然工作中用到的都是公司内部的源,出于安全考虑这里就不拿公司的源举例了~ 1. pip源设置 打开~/.pip/pip.conf文件,若文件不存在则创建文件或者直接mkdir ...

  7. Unix IPC之Posix消息队列(3)

    struct mq_attr { long mq_flags; /* message queue flag : 0, O_NONBLOCK */ long mq_maxmsg; /* max numb ...

  8. Master和worker模式

    让和hadoop的设计思想是一样的,Master负责分配任务和获取任务的结果,worker是真正处理业务逻辑的. 使用ConcurrentLikedQueue去承载所有的任务,因为会有多个worker ...

  9. Sourcetree配置ssh密钥 - git图形化工具(二)

    这里主要介绍Sourcetree如何导入已经生成好的ssh私钥,如何生成ssh私钥自行百度. 如果Sourcetree没有配置ssh密钥,克隆时会提示如下错误: 仓库类型:这是一个无效的源路径/URL ...

  10. pytest mark中的skip,skipif, xfail

    这些测试的过滤,或是对返回值的二重判断, 可以让测试过程更精准,测试结果更可控, 并可以更高层的应用测试脚本来保持批量化执行. import pytest import tasks from task ...