建议:永远使用属性(而不是字段)来暴露数据,即字段永远是 private 或 protected 的。
字段只在类内部使用,类之间交换数据,永远只用属性。
什么是属性
使用 Get/Set 方法对之前:
class Program
{
static void Main(string[] args)
{
var stu1 = new Student()
{
Age = 20
};
var stu2 = new Student()
{
Age = 20
};
var stu3 = new Student()
{
// 非法值,污染字段
Age = 200
};
var avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
Console.WriteLine(avgAge);
}
}
class Student
{
public int Age;
}
使用 Get/Set 后:
class Program
{
static void Main(string[] args)
{
try
{
Student stu1 = new Student();
stu1.SetAge(20);
Student stu2 = new Student();
stu2.SetAge(20);
Student stu3 = new Student();
stu3.SetAge(200);
int avgAge = (stu1.GetAge() + stu2.GetAge() + stu3.GetAge()) / 3;
Console.WriteLine(avgAge);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private int age;
public int GetAge()
{
return this.age;
}
public void SetAge(int value)
{
if (value >= 0 && value <= 120)
{
this.age=value;
}
else
{
throw new Exception("Age value has error.");
}
}
}
使用 Get/Set 来保护字段的方法至今仍在 C++、JAVA 里面流行(即 C++、JAVA 里面是没有属性的)。
因为 Get/Set 写起来冗长,微软应广大程序员请求,给 C# 引入了属性。
引入属性后:
class Program
{
static void Main(string[] args)
{
try
{
Student stu1 = new Student();
stu1.Age = 20;
Student stu2 = new Student();
stu2.Age = 20;
Student stu3 = new Student();
stu3.Age = 200;
int avgAge = (stu1.Age + stu2.Age + stu3.Age) / 3;
Console.WriteLine(avgAge);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private int age;
public int Age
{
get
{
return this.age;
}
set
{
if (value >= 0 && value <= 120)
{
this.age = value;
}
else
{
throw new Exception("Age value has error.");
}
}
}
}
引入属性后代码简洁明了许多。
静态属性:
namespace tttlll
{
class Program
{
static void Main(string[] args)
{
try
{
Student.Amount = -100;
Console.WriteLine(Student.Amount);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private static int amount;
public static int Amount
{
get { return amount; }
set
{
if (value >= 0)
{
Student.amount = value;
}
else
{
throw new Exception("Amount must greater than 0.");
}
}
}
}
属性的声明
Code Snippet
- prop + 2 * TAB:属性的简略声明
- propfull + 2 * TAB:属性的完整声明
- private int age;
(1)用鼠标点击age,点击编辑→重构→封装字段 (2)将光标放在age上,Ctrl+RE
动态计算值的属性
主动计算,每次获取 CanWork 时都计算,适用于 CanWork 属性使用频率低的情况。
class Program
{
static void Main(string[] args)
{
try
{
Student stu = new Student();
stu.Age = 12;
Console.WriteLine(stu.CanWork);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private int age;
public int Age
{
get
{
return age;
}
set
{
age = value;
}
}
public bool CanWork
{
get
{
if (this.age>=16)
{
return true;
}
else
{
return false;
}
}
}
}
被动计算,只在 Age 赋值时计算一次,适用于 Age 属性使用频率低,CanWork 使用频率高的情况。
class Program
{
static void Main(string[] args)
{
try
{
Student stu = new Student();
stu.Age = 12;
Console.WriteLine(stu.CanWork);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
class Student
{
private int age;
public int Age
{
get
{
return age;
}
set
{
age = value;
this.CalculateCanWork();
}
}
private bool canWork;
public bool CanWork
{
get { return canWork; }
}
private void CalculateCanWork()
{
if (this.age>=16)
{
this.canWork = true;
}
else
{
this.canWork = false;
}
}
}