一、简要介绍
属性是代表类的实例或者类中的一个数据项的成员。
属性是字段和方法的交集,指的是一组两个匹配的访问器方法。
下面是属性的基本形式
public 返回类型 标识符{
set 访问器为属性赋值;
get 访问器为属性获取值;
}
属性包含两个代码块,分别以get和set关键字开头。
- get块包含读取属性时候执行的语句
- set块包含在向属性写入时执行的语句。
set访问器和get访问器的特点如下:
- set访问器
- 拥有一个单独的、隐式的参数value,其类型与属性的相同
- set访问器返回类型为void
- get访问器
- 没有参数
- 拥有一个与属性类型相同的返回值。
public 这样的修饰符是可选的,可以选择私有的,这样就不可以在类外直接访问 set 和 get 访问器
通常将类中的字段声明private以封装该字段, 然后声明一个public的属性来控制从类的外部对该字段的访问。
与属性关联的字段称为后备字段。
一般习惯把私有方法和字段以小写字母开头,公共方法和字段以大写字母开头。
使用属性和使用字段是一样的语法
- 从属性取值时,编译器自动将字段风格的代码转换成对属性的get访问器的调用。
- 向属性赋值时,编译器自动将字段风格的代码转换成对该属性的set访问器的调用。
二、详细介绍
2.1 例子
using System;
namespace PropertyDemo
{
internal class Program
{
static void Main(string[] args)
{
PropertyDemo propertyDemo = new PropertyDemo();
propertyDemo.Name = "yyrwkk";
Console.WriteLine(propertyDemo.Name);
Console.ReadKey();
}
}
public class PropertyDemo
{
private string name;
public string Name
{
get { return name; }
set { name = value; }
}
}
}
可以简化语句
public string Name {
get => name;
set => name = value;
}
2.2 属性和字段的比较
- 属性本质是方法而非字段。
- 只有在结构或类初始化好之后,才能通过该结构或类的属性赋值。
- 不能将属性作为ref或out参数传给方法,因为属性并不真正执行一个内存位置,它指向的是一个访问器方法。
- 属性最多只能包含一个get和一个set访问器,不能包含其他方法、字段和属性。
- get和set访问器不能获取任何参数。要赋的值会通过内建的、隐藏的value变量自动传给set访问器
- 不能声明const属性
属性跟字段的相同点
- 都是命名的实例成员
- 都有类型
- 都可以被赋值和读取
属性和字段的不同点
- 属性实际上是一个成员函数
- 不为数据存储分配内存
- 属性可以只读或者只写。
2.3 自动实现属性
允许只声明属性而不声明后备字段,编译器会创建隐藏的后备字段,并且自动挂接到get或者set访问器上。
自动实现属性的要点:
- 不声明后备字段,编译器根据属性的类型分配存储。
- 不能提供访问器的方法体。
- 自动实现的属性本身会自动分配内存。
- 可以创建只读自动属性,但是不能创建只写自动属性。
using System;
namespace PropertyDemo
{
internal class Program
{
static void Main(string[] args)
{
PropertyDemo propertyDemo = new PropertyDemo();
propertyDemo.Name = "yyrwkk";
Console.WriteLine(propertyDemo.Name);
Console.ReadKey();
}
}
public class PropertyDemo
{
//private string name;
public string Name{get;set;}
}
}
2.4 静态属性
属性可以声明为static,静态属性的访问器和所有静态成员一样。
- 不能访问类的实例成员,但是可以访问类的静态成员
- 当从类的外部访问时,必需使用类名进行引用。
using System;
namespace PropertyDemo
{
internal class Program
{
static void Main(string[] args)
{
PropertyDemo.Name = "yyrwkk";
Console.WriteLine(PropertyDemo.Name);
Console.ReadKey();
}
}
public class PropertyDemo
{
//private string name;
public static string Name {get;set;}
}
}
2.5 只读/只写属性
可声明只含get访问器的属性,这称为只读属性,无法修改。
public string Name{
get => name;
}
声明只含set访问器的属性,称为只写属性,无法读取。
public string Name {
set => Name = value;
}
只写属性适用于对密码这样的数据进行保护。
2.6 属性可访问性
声明属性时可以指定可访问性
在属性声明中,可以为set和get访问器单独指定可访问性,从而覆盖属性的可访问性
class PropertyDemo{
private string name;
public string Name {
get => name;
private set => name = value;
}
}
Name的get访问器就是public的,而Name的set访问器就是private的
2.7 接口声明属性
在接口中可以声明属性
interface Position{
int X {get;set;}
int Y {get;set;}
}
实现接口的任何类或者结构都必须实现X和Y属性。
接口中的属性不能指定访问修饰符。
2.8 使用初始化器初始化属性
使用属性初始化对象
using System;
namespace PropertyDemo
{
internal class Program
{
static void Main(string[] args)
{
PropertyDemo propertyDemo = new PropertyDemo() { Age=19,Name="yyrwkk" };
Console.WriteLine(propertyDemo.Name);
Console.ReadKey();
}
}
public class PropertyDemo
{
public int Age { get; set; }
public string Name { get; set; }
}
}
调用对象初始化器,C#编译器会自动生成代码来调用默认构造器,然后调用每个具名属性的set访问器,把它们初始化成指定值。
还可以使用自定义的构造函数
using System;
namespace PropertyDemo
{
internal class Program
{
static void Main(string[] args)
{
PropertyDemo propertyDemo = new PropertyDemo(175) { Age=19,Name="yyrwkk" };
Console.WriteLine(propertyDemo.Name);
Console.ReadKey();
}
}
public class PropertyDemo
{
private int height;
public int Age { get; set; }
public string Name { get; set; }
public PropertyDemo(int height)
{
this.height = height;
}
}
}