可空类型 C#.docx

上传人:b****6 文档编号:5963580 上传时间:2023-01-02 格式:DOCX 页数:10 大小:50.09KB
下载 相关 举报
可空类型 C#.docx_第1页
第1页 / 共10页
可空类型 C#.docx_第2页
第2页 / 共10页
可空类型 C#.docx_第3页
第3页 / 共10页
可空类型 C#.docx_第4页
第4页 / 共10页
可空类型 C#.docx_第5页
第5页 / 共10页
点击查看更多>>
下载资源
资源描述

可空类型 C#.docx

《可空类型 C#.docx》由会员分享,可在线阅读,更多相关《可空类型 C#.docx(10页珍藏版)》请在冰豆网上搜索。

可空类型 C#.docx

可空类型C#

12.2使用泛型

在探讨如何创建自己的泛型之前,先介绍.NETFramework提供的泛型,包括System.Collection.Generic命名空间中的类型,这个命名空间已在前面的代码中出现过多次,因为默认情况下它包含在控制台应用程序中。

我们还没有使用过这个命名空间中的类型,但下面就要使用了。

本节将讨论这个命名空间中的类型,以及如何使用它们创建强类型化的集合,提高已有集合的功能。

首先论述另一个较简单的泛型类型(nullabletype):

可空类型,解决值类型的一个小问题。

12.2.1 可空类型

在前面的章节中,介绍了值类型(大多数基本类型,例如int、double和所有的结构)区别于引用类型(string和所有的类)的一种方式:

值类型必须包含一个值,它们可以在声明之后、赋值之前,在未赋值的状态下存在,但不能以任何方式使用。

而引用类型可以是null。

有时让值类型为空是很有用的,泛型使用System.Nullable类型提供了使值类型为空的一种方式。

例如:

System.NullablenullableInt;

这行代码声明了一个变量nullableInt,它可以拥有int变量能包含的任意值,还可以拥有值null。

所以可以编写下面的代码:

nullableInt=null;

如果nullableInt是一个int类型的变量,上面的代码是不能编译的。

前面的赋值等价于:

nullableInt=newSystem.Nullable();

与其他变量一样,无论是初始化为null(使用上面的语法),还是通过给它赋值来初始化,都不能在初始化之前使用它。

可以像测试引用类型一样,测试可空类型,看看它们是否为null:

if(nullableInt==null)

{

...

}

另外,可以使用HasValue属性:

if(nullableInt.HasValue)

{

...

}

这不适用于引用类型,即使引用类型有一个HasValue属性,也不能使用这种方法,因为引用类型的变量值为null,就表示不存在对象,当然就不能通过对象来访问这个属性,此时会抛出一个异常。

使用Value属性可以查看引用类型的值。

如果HasValue是true,就说明Value属性有一个非空值。

但如果HasValue是false,就说明变量被赋予了null,访问Value属性会抛出System.InvalidOperationException类型的异常。

可空类型要注意的一点是,它们非常有用,以致于修改了C#语法。

上面可空类型的变量不使用上述语法,而是使用下面的语法:

int?

nullableInt;

int?

是System.Nullable的缩写,但可读性更高。

在后面的章节中就使用这个语法。

1.运算符和可空类型

对于简单类型如int,可以使用+、–等运算符来处理值。

而对于可空类型,这是没有区别的:

包含在可空类型中的值会隐式转换为需要的类型,使用适当的运算符。

这也适用于结构和自己提供的运算符。

例如:

int?

op1=5;

int?

result=op1*2;

注意其中result变量的类型也是int?

下面的代码不会编译:

int?

op1=5;

intresult=op1*2;

为了使上面的代码正常工作,必须进行显式转换:

int?

op1=5;

intresult=(int)op1*2;

只要op1有一个值,上面的代码就可以正常运行,如果op1是null,就会生成System.InvalidOperationException类型的异常。

这就引出了下一个问题:

当运算等式中的一个或两个值是null时,例如上面代码中的op1,会发生什么情况?

答案是:

对于除了bool?

之外的所有简单可空类型,该操作的结果是null,可以把它解释为“不能计算”。

对于结构,可以定义自己的运算符来处理这种情况(详见本章后面的内容)。

对于bool?

,为&和|定义的运算符会得到非空返回值,如表12-1所示。

表 12-1

op1

op2

op1&op2

op1|op2

true

true

true

true

true

false

false

true

true

null

null

true

false

true

false

true

false

false

false

false

false

null

false

null

null

true

null

true

null

false

false

null

null

null

null

null

这些运算符的结果与我们想像的一样,如果不需要知道其中一个操作数的值,就可以计算出结果,则该操作数是否为null就不重要。

2.?

?

运算符

为了进一步减少处理可空类型所需的代码量,使可空变量的处理变得更简单,可以使用?

?

运算符。

这个运算符允许提供可空类型是null和不是null时的默认值,其用法如下:

int?

op1=null;

intresult=op1*2?

?

5;

在这个示例中,op1是null,所以op1*2也是null。

但是,?

?

运算符检测到这个情况,并把值5赋予result。

这里特别要注意,在结果中放入int类型的变量result不需要显式转换。

?

?

运算符会自动处理这个转换。

可以把?

?

等式的结果放在int?

中:

int?

result=op1*2?

?

5;

在处理可空变量时,?

?

运算符有许多用途,它也是提供默认值的一种方便方式,不需要使用if结构中的代码块。

在下面的示例中,将介绍可空类型Vector。

试试看:

可空类型

(1)在目录C:

\BegVCSharp\Chapter12下创建一个新控制台应用程序项目Ch12Ex01。

(2)使用VS快捷方式,在文件Vector.cs中添加一个新类Vector。

(3)修改Vector.cs中的代码,如下所示:

publicclassVector

{

publicdouble?

R=null;

publicdouble?

Theta=null;

publicdouble?

ThetaRadians

{

get

{

//Convertdegreestoradians.

return(Theta*Math.PI/180.0);

}

}

publicVector(double?

r,double?

theta)

{

//Normalize.

if(r<0)

{

r=-r;

theta+=180;

}

theta=theta%360;

//Assignfields.

R=r;

Theta=theta;

}

publicstaticVectoroperator+(Vectorop1,Vectorop2)

{

try

{

//Get(x,y)coordinatesfornewvector.

doublenewX=op1.R.Value*Math.Sin(op1.ThetaRadians.Value)

+op2.R.Value*Math.Sin(op2.ThetaRadians.Value);

doublenewY=op1.R.Value*Math.Cos(op1.ThetaRadians.Value)

+op2.R.Value*Math.Cos(op2.ThetaRadians.Value);

//Convertto(r,theta).

doublenewR=Math.Sqrt(newX*newX+newY*newY);

doublenewTheta=Math.Atan2(newX,newY)*180.0/Math.PI;

//Returnresult.

returnnewVector(newR,newTheta);

}

catch

{

//Return"null"vector.

returnnewVector(null,null);

}

}

publicstaticVectoroperator-(Vectorop1)

{

returnnewVector(-op1.R,op1.Theta);

}

publicstaticVectoroperator-(Vectorop1,Vectorop2)

{

returnop1+(-op2);

}

publicoverridestringToString()

{

//Getstringrepresentationofcoordinates.

stringrString=R.HasValue?

R.ToString():

"null";

stringthetaString=Theta.HasValue?

Theta.ToString():

"null";

//Return(r,theta)string.

returnstring.Format("({0},{1})",rString,thetaString);

}

}

(4)修改Program.cs中的代码,如下所示:

classProgram

{

publicstaticvoidMain(string[]args)

{

Vectorv1=GetVector("vector1");

Vectorv2=GetVector("vector1");

Console.WriteLine("{0}+{1}={2}",v1,v2,v1+v2);

Console.WriteLine("{0}-{1}={2}",v1,v2,v1-v2);

Console.ReadKey();

}

publicstaticVectorGetVector(stringname)

{

Console.WriteLine("Input{0}magnitude:

",name);

double?

r=GetNullableDouble();

Console.WriteLine("Input{0}angle(indegrees):

",name);

double?

theta=GetNullableDouble();

returnnewVector(r,theta);

}

publicstaticdouble?

GetNullableDouble()

{

double?

result;

stringuserInput=Console.ReadLine();

try

{

result=double.Parse(userInput);

}

catch

{

result=null;

}

returnresult;

}

}

(5)执行应用程序,给两个矢量(vector)输入值,结果如图12-1所示。

图12-1

(6)再次执行应用程序,这次跳过四个值中的至少一个,结果如图12-2所示。

图12-2

示例的说明

在这个示例中,创建了一个类Vector,它表示带极坐标(有一个幅值和一个角度)的矢量,如图12-3所示。

图12-3

坐标r和_在代码中用公共字段R和Theta表示,其中Theta的单位是度(°)。

ThetaRad用于获取Theta的弧度值,这是必须的,因为Math类在其静态方法中使用弧度。

R和Theta的类型都是double?

,所以它们可以为空。

publicclassVector

{

publicdouble?

R=null;

publicdouble?

Theta=null;

publicdouble?

ThetaRadians

{

get

{

//Convertdegreestoradians.

return(Theta*Math.PI/180.0);

}

}

Vector的构造函数标准化R和Theta的初始值,然后赋予公共字段。

publicVector(double?

r,double?

theta)

{

//Normalize.

if(r<0)

{

r=-r;

theta+=180;

}

theta=theta%360;

//Assignfields.

R=r;

Theta=theta;

}

Vector类的主要功能是使用运算符重载对矢量进行相加和相减,这需要一些非常基本的三角函数知识,这里不解释它们。

在代码中,重要的是,如果在获取R或ThetaRad的Value属性时抛出了异常,即其中一个是null,就返回“空”矢量。

publicstaticVectoroperator+(Vectorop1,Vectorop2)

{

try

{

//Get(x,y)coordinatesfornewvector.

...

}

catch

{

//Return"null"vector.

returnnewVector(null,null);

}

}

如果组成矢量的坐标是null,该矢量就是无效的,这里用R和Theta都可为null的Vector类来表示。

Vector类的其他代码重写了其他运算符,把相加的功能扩展到相减上,再重写ToString(),获取Vector对象的字符串表示。

Program.cs中的代码测试Vector类,让用户初始化两个矢量,再对它们进行相加和相减。

如果用户省略了一个值,该值就解释为null,应用前面提及的规则。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 自然科学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1