为了促进代码的重用,尤其是算法的重用,C#现在支持一种名为泛型的特性。方法因为能获取参数而变得强大,类似地,类也因为能获取类型参数而变得强大——这正式泛型的主旨。
我们利用泛型来创建特殊的类和方法,这些类的方法将一个或多个类型的指定推迟到客户端代码声明并实例化该类的方法的时候。程序员定义这种参数化类型,是特定泛型类型的每个变量都有相同的内部算法,但数据类型和方法签名可以根据程序员的偏爱而不同。
今天我们来学习泛型的一个基本例子,可空类型。
大多数的值类型,例如int、double和所有的结构,区别于引用类型(string和所有类)的一种方式:
值必须包括一个值,它们可以在声明之后,赋值之前,在没有赋值的状态下存在,但不能以任何方式使用。而引用类型可以是null。有时候可以让值类型为空是很有用的,泛型使用System.Nullable<T>类型提供了使值类型为空的一种方式。如:
System.Nullable<int> nullableInt
System.Nullable<int> nullableInt
可空类型非常有用,以至于修改了C#语法,上述表达等效于:
int ? nullableInt
测试代码:
using System ;
using System .Collections.Generic ;
using System .Text ;
public class Nullable
{
static void Main()
{
int ? op1 = null ;
int ? result = null ;
Console.WriteLine ( " Please Enter The Number: " );
try
{
op1 = Int32.Parse (Console.ReadLine ());
result = op1 * op1;
}
catch
{
op1 = null ;
result = null ;
}
Console.WriteLine (result.ToString ());
}
}
测试结果:
int ? nullableInt
测试代码:
using System ;
using System .Collections.Generic ;
using System .Text ;
public class Nullable
{
static void Main()
{
int ? op1 = null ;
int ? result = null ;
Console.WriteLine ( " Please Enter The Number: " );
try
{
op1 = Int32.Parse (Console.ReadLine ());
result = op1 * op1;
}
catch
{
op1 = null ;
result = null ;
}
Console.WriteLine (result.ToString ());
}
}
测试结果:
下面为另一个可空类型的例子,稍微复杂一点:
Vector类:
#region Using Directive
using System ;
using System .Collections .Generic ;
using System .Text ;
#endregion
public class Vector
{
public double? R=null; // declare unllable,the same as System.Nullable<double>
public double? Theta=null;
public double? ThetaRadians // ??
{
get
{
// Convert degrees to radians
return (Theta * Math.PI /180.0);
}
}
// ??????
public Vector(double ? r,double? theta)
{
// Normalize
if (r<0)
{
r=-r;
theta+=180;
}
theta=theta%360;
// Assign fields
R=r;
Theta=theta;
}
//Use Add Method to Get a new Vector
public static Vector operator +(Vector op1,Vector op2)
{
try
{
// Get (x,y) coordinates for new vector
double newX=op1.R .Value *Math.Sin (op1.ThetaRadians .Value +op2.R .Value *Math.Sin (op2.ThetaRadians .Value );
double newY=op1.R .Value *Math.Cos (op1.ThetaRadians .Value +op2.R .Value *Math.Cos (op2.ThetaRadians .Value );
// Convert to (r,theta)
double newR=Math.Sqrt (newX*newX+newY*newY);
double newTheta=Math.Atan2 (newX,newY)*180.0/Math.PI ;
// Return result
return new Vector (newR,newTheta);
}
catch
{
// Return "null" Vector
return new Vector (null,null);
}
}
public static Vector operator-(Vector op1)
{
return new Vector (-op1.R ,op1.Theta );
}
public static Vector operator - (Vector op1,Vector op2)
{
return op1+(-op2);
}
public override string ToString()
{
//Get string repersentation of coordinats
string rString =R.HasValue ? R.ToString ():"null";
string thetaString=Theta.HasValue ? Theta.ToString ():"null";
//Return (r,theta) string
return string .Format ("({0},{1})",rString ,thetaString);
}
}
Vector类:
#region Using Directive
using System ;
using System .Collections .Generic ;
using System .Text ;
#endregion
public class Vector
{
public double? R=null; // declare unllable,the same as System.Nullable<double>
public double? Theta=null;
public double? ThetaRadians // ??
{
get
{
// Convert degrees to radians
return (Theta * Math.PI /180.0);
}
}
// ??????
public Vector(double ? r,double? theta)
{
// Normalize
if (r<0)
{
r=-r;
theta+=180;
}
theta=theta%360;
// Assign fields
R=r;
Theta=theta;
}
//Use Add Method to Get a new Vector
public static Vector operator +(Vector op1,Vector op2)
{
try
{
// Get (x,y) coordinates for new vector
double newX=op1.R .Value *Math.Sin (op1.ThetaRadians .Value +op2.R .Value *Math.Sin (op2.ThetaRadians .Value );
double newY=op1.R .Value *Math.Cos (op1.ThetaRadians .Value +op2.R .Value *Math.Cos (op2.ThetaRadians .Value );
// Convert to (r,theta)
double newR=Math.Sqrt (newX*newX+newY*newY);
double newTheta=Math.Atan2 (newX,newY)*180.0/Math.PI ;
// Return result
return new Vector (newR,newTheta);
}
catch
{
// Return "null" Vector
return new Vector (null,null);
}
}
public static Vector operator-(Vector op1)
{
return new Vector (-op1.R ,op1.Theta );
}
public static Vector operator - (Vector op1,Vector op2)
{
return op1+(-op2);
}
public override string ToString()
{
//Get string repersentation of coordinats
string rString =R.HasValue ? R.ToString ():"null";
string thetaString=Theta.HasValue ? Theta.ToString ():"null";
//Return (r,theta) string
return string .Format ("({0},{1})",rString ,thetaString);
}
}
客户代码:
using System;
using System.Collections.Generic;
namespace Nullable
{
class MainClass
{
public static void Main(string[] args)
{
Vector v1=GetVector ("vector1");
Vector v2=GetVector ("vector2");
Console.WriteLine ("{0}+{1}={2}",v1,v2,v1+v2);
Console.WriteLine ("{0}-{1}={2}",v1,v2,v1-v2);
Console.ReadLine ();
}
public static Vector GetVector(string name)
{
Console.WriteLine ("Input {0} magnitude:",name);
double ? r=GetNullableDouble();
Console.WriteLine ("Input {0} angle (in degrees):",name);
double? theta=GetNullableDouble();
return new Vector (r,theta);
}
public static double? GetNullableDouble()
{
double? result;
string userInput=Console.ReadLine ();
try
{
result=double.Parse (userInput);
}
catch
{
result=null;
}
return result;
}
}
}
using System;
using System.Collections.Generic;
namespace Nullable
{
class MainClass
{
public static void Main(string[] args)
{
Vector v1=GetVector ("vector1");
Vector v2=GetVector ("vector2");
Console.WriteLine ("{0}+{1}={2}",v1,v2,v1+v2);
Console.WriteLine ("{0}-{1}={2}",v1,v2,v1-v2);
Console.ReadLine ();
}
public static Vector GetVector(string name)
{
Console.WriteLine ("Input {0} magnitude:",name);
double ? r=GetNullableDouble();
Console.WriteLine ("Input {0} angle (in degrees):",name);
double? theta=GetNullableDouble();
return new Vector (r,theta);
}
public static double? GetNullableDouble()
{
double? result;
string userInput=Console.ReadLine ();
try
{
result=double.Parse (userInput);
}
catch
{
result=null;
}
return result;
}
}
}