按照我的理解,泛型指的是“加强的类型”。举例来说,我们使用传统的基础数据类型,int,float,double这样的变量,需要先声明再赋值然后才能引用,但是如果声明了没赋值就开始引用呢?那么就会报错。但是有时候,对于一些程序中的某些变量而言,空(null)是被允许而且在有些情况下是有意义的,那这时候我们就要使用泛型。
对于基础数据类型的泛型来说,区别仅仅在于它可以为空,接下来用一个例子进行说明,该例子是在控制台中由用户输入两个向量,然后计算出两个向量的和向量。在输入的时候,可能会出现向量的某个值为空的情况。
(一):创建新的控制台程序,新建新类Vector,将该类设置为public级别,在预处理部分写上using static System.Math;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
namespace Ch12Ex01
{
public class Vector
{
}
}
向量我们一般使用一个距离r和一个角度theta来表示,因此我们需要两个字段分别表示,因为我们这里可能会出现null的情况,因此使用泛型来表示这两个字段,
public double? R = null;
public double? Theta = null;
这里的Theta是用角度来表示,但是System.Math里提供的函数都是使用的弧度制,因此我们设置一个泛型属性作为弧度。
public double? ThetaRadians
{
get { return (Theta * PI / 180.0); }
}
在输入向量的过程中可能会出现r为负数的情况,为了避免这种情况,修改构造函数
public Vector(double? r,double? theta)
{
if(r<0)
{
r = -r;
theta += 180;
}
theta = theta % 360;
R = r;
Theta = theta;
}
重新定义"+"的运算,
public static Vector operator +(Vector op1,Vector op2)
{
try
{
double newY = op1.R.Value * Sin(op1.ThetaRadians.Value)
+ op2.R.Value * Sin(op2.ThetaRadians.Value);
double newX = op1.R.Value * Cos(op1.ThetaRadians.Value)
+ op2.R.Value * Cos(op2.ThetaRadians.Value);
double newR = Sqrt(newX * newX + newY * newY);
double newTheta = Atan2(newY, newX) * 180 / PI;
return new Vector(newR, newTheta);
}
catch
{
return new Vector(null, null);
}
}
接下来在Program类中,编写获取输入值的方法
static double? GetNullableDouble()
{
double? result;
string userInput = ReadLine();
try
{ result = double.Parse(userInput); }
catch
{ result = null; }
return result;
}
编写获取向量的方法
static Vector GetVector(string name)
{
WriteLine($"Input {name} magnitude:");
double? r = GetNullableDouble();
WriteLine($"Input {name} angle (in degrees):");
double? theta = GetNullableDouble();
return new Vector(r, theta);
}
最后在主函数写上
Vector v1 = GetVector("Vector1");
Vector v2 = GetVector("Vector2");
WriteLine($"{v1}+{v2}={v1 + v2}");
WriteLine($"{v1}-{v2}={v1 - v2}");
ReadKey();
(二):程序运行结果
1:正常输入
2:输入时有一个值为空
(三):总结
从这个案例来看似乎泛型也不是很难?也就是原来的基础数据结构加上了个空值判断。
(四):源代码
1:Program类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
namespace Ch12Ex01
{
class Program
{
static void Main(string[] args)
{
Vector v1 = GetVector("Vector1");
Vector v2 = GetVector("Vector2");
WriteLine($"{v1}+{v2}={v1 + v2}");
WriteLine($"{v1}-{v2}={v1 - v2}");
ReadKey();
}
static Vector GetVector(string name)
{
WriteLine($"Input {name} magnitude:");
double? r = GetNullableDouble();
WriteLine($"Input {name} angle (in degrees):");
double? theta = GetNullableDouble();
return new Vector(r, theta);
}
static double? GetNullableDouble()
{
double? result;
string userInput = ReadLine();
try
{ result = double.Parse(userInput); }
catch
{ result = null; }
return result;
}
}
}
2:Vector类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Math;
namespace Ch12Ex01
{
public class Vector
{
public double? R = null;
public double? Theta = null;
public double? ThetaRadians
{
get { return (Theta * PI / 180.0); }
}
public Vector(double? r,double? theta)
{
if(r<0)
{
r = -r;
theta += 180;
}
theta = theta % 360;
R = r;
Theta = theta;
}
public static Vector operator +(Vector op1,Vector op2)
{
try
{
double newY = op1.R.Value * Sin(op1.ThetaRadians.Value)
+ op2.R.Value * Sin(op2.ThetaRadians.Value);
double newX = op1.R.Value * Cos(op1.ThetaRadians.Value)
+ op2.R.Value * Cos(op2.ThetaRadians.Value);
double newR = Sqrt(newX * newX + newY * newY);
double newTheta = Atan2(newY, newX) * 180 / PI;
return new Vector(newR, newTheta);
}
catch
{
return new Vector(null, null);
}
}
///
public static Vector operator -(Vector op1)=>new Vector(-op1.R,op1.Theta);
public static Vector operator -(Vector op1,Vector op2)=>op1+(-op2);
public override string ToString()
{
string rString = R.HasValue ? R.ToString() : "null";
string thetaString = Theta.HasValue ? Theta.ToString() : "null";
return string.Format($"({rString},{thetaString})");
}
}
}