c#支持this关键字来提供对当前类实例的访问。在“c#与.Net4高级程序设计”中说到this关键字的作用:this关键字可能的用途就是,
解决当传入参数的名字与类型数据字段的名字相同时产生的作用域歧义;其次可以
使用this关键字串联构造函数,即所谓的构造函数链,当类定义了多个构造函数时,这种设计模式就很有用。在.Net4以上的版本中还可以通过命名参数和可选参数进行构造函数链的设计,这种设计使代码更为简洁。
下面通过代码说明:
一、下面定义了各种不同的模拟汽车的Car类:(用来验证this关键字第二个作用)
namespace this关键字
{
/// <summary>
/// 此类未使用构造函数链来设计类,存在冗余代码
/// </summary>
class Car
{
private int wheels;
private string carName;
public Car() { }
//下面的两个构造函数存在冗余的验证逻辑,如果业务规则改变的话就必须在多个地方更新代码
public Car(int wheels)
{
if (wheels < 0)
{
wheels = 4;
}
this.wheels = wheels;
}
public Car(int wheels, string carName)
{
if (wheels < 0)
{
wheels = 4;
}
this.wheels = wheels;
this.carName = carName;
}
}
/// <summary>
/// 此类用来演示使用this关键字进行串联构造函数调用,即所谓的构造函链技术来设计类,解决冗余的问题
/// </summary>
class Car2
{
private int wheels;
private string carName;
public int Wheels
{
get { return this.wheels; }
}
public string CarName
{
get { return this.carName; }
}
public Car2():this(4,"unknow") { }
//下面两个构造函数使用this关键字进行串联主构造函数,主构造函数执行完后,再继续执行自己内部的剩余的代码
public Car2(int wheels) : this(wheels, "") { Console.WriteLine("设置轮子数的构造函数"); }
public Car2(string carName) : this(0, carName) { Console.WriteLine("设置汽车名称的构造函数"); }
//这里是实现验证逻辑或业务规则的“主”构造函数
public Car2(int wheels, string carName)
{
if (wheels<0)
{
wheels = 4;
}
this.wheels = wheels;
this.carName = carName;
Console.WriteLine("设置轮子数和汽车名称的主构造函数");
}
}
/// <summary>
/// 此类使用可选参数和命名参数进行构造函数链的设计,这种设计模式只有在.Net4及以上的版本中存在,使用这种方进行设计类可以只提供一个主构造函数,但却有多种调用方式,跟普通的构造函数链技术一样
/// </summary>
class Car3
{
private int wheels;
private string carName;
public int Wheels
{
get { return this.wheels; }
}
public string CarName
{
get { return this.carName; }
}
//只提供一个主构造函数进行所有的逻辑验证,但可以以0个、1个、2个参数进行调用,配合使用命名参数可以跳过提供的默认值,具体应用见Program.cs文件
public Car3(int wheels = 4, string carName = "")
{
if (wheels < 0)
{
wheels = 4;
}
this.wheels = wheels;
this.carName = carName;
}
}
}
二、下面定义两个自行车Cycle类,用来验证this关键字的第一个作用
/// <summary>
/// 未使用this关键字的类,存在同名歧义
/// </summary>
class Cycle
{
private int weight;
public string driveName;
public void setDriveName(string driveName)
{
driveName = driveName;//这句话会产生歧义,编译器发出警告提示对同一变量进行赋值,编译器认为driveName指向当前方法作用域内的变量,而不是类中的driveName字段。
}
}
/// <summary>
/// 使用this关键字的类,解决了同名歧义的问题
/// </summary>
class Cycle2
{
public string driveName;
public void setDriveName(string driveName)
{
this.driveName = driveName;//使用this关键字解决歧义
}
}
下面是Program主类
class Program
{
static void Main(string[] args)
{
Cycle c = new Cycle();
c.setDriveName("Tiny");
Console.WriteLine("drive name is {0}", c.driveName);//这句话会输出一个空字符串,可以使用this关键字解决歧义。
Cycle2 c2 = new Cycle2();
c2.setDriveName("Tiny");
Console.WriteLine("drive name is {0}", c2.driveName);//这句话会正常输出,同名问题得以解决
Console.WriteLine();
//下面的代码验证使用了构造函数链技术的类的优点,解决了代码冗余的问题
Car2 l1 = new Car2();
Console.WriteLine("Ca2:\t wheels is {0},carName is {1} ", l1.Wheels, l1.CarName);
Car2 l2 = new Car2(3);
Console.WriteLine("Ca2:\t wheels is {0},carName is {1} ", l2.Wheels, l2.CarName);
Car2 l3 = new Car2("法拉利");
Console.WriteLine("Ca2:\t wheels is {0},carName is {1} ", l3.Wheels, l3.CarName);
Console.WriteLine();
//下面的代码验证使用可选参数和命名参数进行构造函数链设计的类的优点
Car3 m1 = new Car3();
Console.WriteLine("Car3:\t wheels is {0},carName is {1} ", m1.Wheels, m1.CarName);
Car3 m2 = new Car3(3);
Console.WriteLine("Car3:\t wheels is {0},carName is {1} ", m2.Wheels, m2.CarName);
Car3 m3 = new Car3(carName:"兰博基尼");//使用命名参数跳过第一个参数
Console.WriteLine("Car3:\t wheels is {0},carName is {1} ", m3.Wheels, m3.CarName);
Console.ReadKey();
}
}