/// <summary>
/// 第十五章:实现属性以访问字段
/// </summary>
namespace Chapter15
{
class Program
{
static void Main(string[] args)
{
//15.1使用方法实现封装
/*使用公共字段,代码无疑更简洁,缺点是会破坏封装性.
*不过,在属性的帮助下,可以获得两全其美的结果,即维护了封装性,又能使用字段风格的语法
*/
//15.2什么是属性(属性包含两个代码块get\set)
///15.2.1使用属性
ScreenPosition screenPosition = new ScreenPosition();
int xpos = screenPosition.X;
int ypos = screenPosition.Y;
///15.2.2只读属性(把属性设为私有)
///15.2.3只写属性(只包含set)
///15.2.4属性的可访问性
/*
* 为两个访问器定义不同的可访问性时,必须遵守以下规则:『
* 1.只能改变一个访问器的可访问性。(例如,将属性声明为公共,但将它的两个访问器都声明成私有是没有意义的。)
* 2.访问器的访问修饰符所指定的可访问性在限制程度上必须大于属性的可访问性。
* 』
*/
//15.3理解属性的局限性
/*
* 属性的限制:
* 只有在结构或类初始化好之后,才能通过该结构或类的属性来赋值。
* 不能将属性作为ref或out参数传给方法;但可写的字段能作为ref或out参数传递。
* 属性最多只能包含一个get和一个set访问器。不能包含其他方法、字段或属性。
* get和set访问器不能获取任何参数。
* 不能声明const属性
*/
///15.4.1用属性替代方法
///略
///15.4.2生成自动属性
/*
* 与应用程序的兼容性
* 与接口的兼容性
*/
//15.6用属性初始化对象
//对象初始化器或初始化列表
Triangle tri1 = new Triangle { Side1Length = 15 };
/*
* 自动属性和不可变性:
* class Grade{
* public int StudentID(get;init;)//调用赋值之后就不可更改
* }
*/
//15.7用带属性的“记录”来实现轻量级结构
}
/// <summary>
/// 15.4在接口中声明属性
/// </summary>
interface IScreenPosition
{
int x { get; set; }
int y { get; set; }
}
struct ScreenPosition : IScreenPosition
{
//三种方法实现
//第一种
public int x { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public int y { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
//第二种:允许派生类重写
//public virtual int x { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
//第三种:使用显示接口实现语法
//int IScreenPosition.x
//{
// get {... }
// set {... }
//}
}
/// <summary>
/// 15.5生成自动属性
/// </summary>
public class Cirle
{
//第二种
//public Cirle()
//{
// CircleCreatedDate = DateTime.Now;
//}
//第一种
private int radius;
public int Radius
{
get
{
return this.radius;
}
set
{
this.radius = value;
}
}
//第三种
//public DateTime CircleCreatedDate(get;) =DateTime.Now;
}
/// <summary>
/// 15.6用属性初始化对象
/// </summary>
public class Triangle
{
private int side1Length;
private int side2Length;
private int side3Length;
public Triangle()
{
this.side1Length = this.side2Length = this.side3Length = 10;
}
public Triangle(int length1)
{
this.side1Length = length1;
this.side2Length = this.side3Length = 10;
}
public Triangle(int length1, int length2)
{
this.side1Length = length1;
this.side2Length = length2;
}
public Triangle(int length1,int length2,int length3)
{
this.side1Length = length1;
this.side2Length = length2;
this.side3Length = length3;
}
/// <summary>
/// 定义获取可选参数的构造器,并在创建对象时,通过指定参数名的方式为特定参数传递实参(具名参数)
/// </summary>
public int Side1Length
{
set => this.side1Length = value;
}
}
}
}
namespace Chapter15.Moudle
{
public struct ScreenPosition{
public int x;
public int y;
public ScreenPosition(int x, int y)
{
this.x = x;
this.y = y;
}
private static int rangecheckedx(int x)
{
if (x < 0 || x > 1279)
{
throw new ArgumentOutOfRangeException("x");
}
return x;
}
private static int rangecheckedy(int y)
{
if (y < 0 || y > 1023)
{
throw new ArgumentOutOfRangeException("y");
}
return y;
}
/*
* 违反了封装原则,没有保持数据的私有状态。
*/
public int GetX()
{
return this.x;
}
public int GetY()
{
return this.y;
}
public void SetX(int newX)
{
this.x = rangecheckedx(newX);
}
public void SetY(int newY)
{
this.x = rangecheckedx(newY);
}
/// <summary>
/// 简单属性
/// </summary>
public int X
{
get => this.X;
set => this.x = rangecheckedx(value);
}
/// <summary>
/// 简单属性
/// </summary>
public int Y
{
get => this.Y;
set => this.Y = rangecheckedx(value);
}
}
}