目录
1、字段
2、注意事项:
3、属性
4、什么是索引器
5、什么是常量
1、字段
什么是字段
- 字段(field)是一种表示与对象或类型(类与结构体)关联的变量的成员
- 字段是类型的成员,旧称“成员变量”
- 与对象关联的字段称为“实例字段”
- 与类型关联的字段称为“静态字段”,由static修饰
字段的声明
- 尽管字段声明带有分号,但它不是语句。
- 字段的名字一定是个名词。
字段的初始值
- 无显示初始化时,字段获得其类型的默认值,所以字段“永远都不会未被初始化”
- 实例字段初始化的时机-----对象创建时
- 静态字段初始化的时机-----类型被加载时(load)
只读字段
- 实例只读字段
- 静态只读字段
字段是定义在方法外面的变量,是成员变量,主要是为了类的内部数据交换使用,字段一般是用private修饰,也可以用readonly修饰,表示只读字段,其他修饰符比较少用,字段是用来存储数据的。
字段声明的格式:[访问修饰符]数据类型 字段名 = [初始值]
例如:private string MyName = string.empty;
属性可以理解为对数据的存储,是一种方法,是字段的封装(字段才是对数据的保存单元),一般对外提供访问,可以添加需要的逻辑,属性一般都是用public进行修饰。
总结:属性可以说是字段的扩展,字段是存储数据的单元,而属性本身不存储数据,可以说是对数据的操作,拥有自己的业务逻辑,获取数据,对数据处理,返回处理后的数据等。
属性的定义是get访问器和set访问器组成,get访问器就是对字段值进行读取,而set访问器就是对字段进行赋值,就是对字段操作的两个方法。
2、注意事项:
(1)定义属性时,类型必须与它所访问的字段类型一致。
(2)一般情况下,字段的名称是小写的,属性的名称与字段名称一样,只是首字母要大写。属性的类型定义属性,我们可以给他设定值,也可以获取它的值。如果想保护属性关联的字段,则只允许读数据,或者只允许写数据,
那么应该如何设定呢?
属性除了可以约束数据访问外,还可以设定设置读写属性,来限定它的访问类型,我们可以设置该属性为只读属性,这种情况下,我们就只能读取字段的值而不能赋值,属性的访问分类为以下三种:
---只读属性,只包含get访问器
---只写属性,只包含set访问器
---读写属性,包含get和set访问器
get和set访问器的灵活运用,可以保障类中字段的安全。
using System;
namespace 字段2
{
class Program
{
static void Main(string[] args)
{
System.Console.OutputEncoding = System.Text.Encoding.UTF8;
#region 字段和属性
/*
//C1初始化实例
C1 c1 = new C1();
//把属性看做一个字段,从中读取它的值;
Console.WriteLine("realValue:{0}", c1.RealValue);
//通过set访问器进行赋值
c1.RealValue = 25;
Console.WriteLine("realValue:{0}",c1.RealValue);
Console.WriteLine();
//C2初始化实例
C2 c2 = new C2();
Console.WriteLine("属性值:{0}", c2.RealValue);
//赋值
c2.RealValue = 47;
Console.WriteLine("属性值:{0}", c2.RealValue);
Console.WriteLine();
*/
#endregion
#region 属性不与字段关联
/*
//Triangle初始化实例
Triangle tri = new Triangle();
Console.WriteLine("三角形第三边长度:{0}",tri.GetThird);
//进行赋值
tri.a = 50;
tri.b = 40;
Console.WriteLine("三角形第三边长度:{0}", tri.GetThird);
Console.WriteLine();
*/
#endregion
#region Person传值
//输出姓名,年龄
//初始化实例
Person son = new Person();
//通过方法给字段赋值
son.SetName("天天");
//通过属性给字段赋值
son.Age = 5;
son.print();
#endregion
#region 初始化实例输出手机信息
MyPhone1 phone = new MyPhone1();
phone.PhoneID = 888;
phone.PhoneName = "华为至尊旗舰手机";
phone.PhonePrice = 9999999;
phone.OnLine = Convert.ToDateTime("2016-08-20");
Console.WriteLine("手机编号为:{0}",phone.PhoneID);
Console.WriteLine("手机名称为:{0}", phone.PhoneName);
Console.WriteLine("手机价格为:{0}", phone.PhonePrice);
Console.WriteLine("手机上线日期为:{0}", phone.OnLine);
//因为是只读属性所以不能进行赋值
Console.WriteLine("手机销售年限为:{0}", phone.SellYears);
#endregion
#region 属性、用户注册登录实验
User user = new User();
Console.WriteLine("=========用户注册=========");
Console.Write("请输入用户名:");
user.Login = Console.ReadLine();
Console.Write("请输入密码:");
user.Password = Console.ReadLine();
Console.Write("请输入性别:");
user.Danger = Console.ReadLine();
Console.WriteLine("=========用户信息=========");
user.DisPlayinfo();
#endregion
Console.ReadKey();
}
}
#region 字段和属性
///
/// 字段与属性都是类的成员。字段是数据成员,是隶属于类的变量。
///属性是函数成员,它不为数据存储分配内寸,它执行代码。
///
class C1
{
private int realValue; //分配内存
public int RealValue //不分配内存
{
//get访问器必须包含return语句,返回字段realValue
get //只读字段
{
return realValue;
}
//set访问器接受它的输入参数--value,并将它赋给字段,value是隐式参数
set //只写字段
{
realValue = value;
}
}
}
///
/// 自动实现属性,C#允许只声明属性而不声明后续字段,编译器会创建隐藏的后备字段,
/// 并且自动挂载到get,set访问器上
///
class C2
{
//分配内存
public int RealValue
{
get;
set;
}
}
#endregion
#region 属性也可以不与字段关联
class Triangle
{
public double a = 20;
public double b = 40;
public double GetThird
{
//只读
get
{
return Math.Sqrt((a+a)*(b+b));
}
}
}
#endregion
#region 输出传值
class Person
{
private string name;
//定义Getname的方法
public string GetName()
{
return name;
}
//定义Setname方法,显示定义value参数
public void SetName(string value)
{
this.name = value;
}
private int age;
public int Age //属性
{
private get
{
return age;
}
set
{
if (value<0||value>120)
{
Console.WriteLine("输入的年龄无效,请重输入!");
}
else
{
this.age = value;
}
}
}
//输出方法
public void print()
{
Console.WriteLine("name:{0},age={1}",name,age);
}
}
#endregion
#region 手机类、手机编号、手机名称、手机价格、上线日期、销售年期
/*
public class MyPhone
{
//定义一组手机数据
private int phoneID;
private string phoneName;
private int phonePrice;
private DateTime onLine;
private readonly int sellYears;
}
*/
public class MyPhone1
{
//私有字段,公有属性
private int phoneID;
//定义手机ID\PhoneID
public int PhoneID
{
get{return phoneID;}
set
{
if (value <0)
{
phoneID = 1000;
}
else
{
phoneID = value;
}
}
}
//定义手机名字phoneName
private string phoneName;
public string PhoneName
{
get { return phoneName; }
set { phoneName = value; }
}
//定义手机价格phonePrice
private int phonePrice;
public int PhonePrice
{
get { return phonePrice; }
set { phonePrice = value; }
}
//上线日期
private DateTime onLine;
public DateTime OnLine
{
get { return onLine; }
set { onLine = value; }
}
//销售年期
private int sellYears;
public int SellYears
{
//设置为只读属性
get { return DateTime.Now.Year - onLine.Year-1; }
}
}
#endregion
#region C#属性的应用1、打个比方我们有个网站,每当有新用户注册的时候,我们需要记录这些用户的信息。创建一个User类来记录用户的注册信息,包括用成员变量(字段)用户名,密码,性别。
///2、用属性封装3个字段,实现赋值规则用户名只能以字母开头,密码长度不小于6(默认6个1),性别只能是“男”或“女”。
/// 3、为User类添加公共的DisplayInfo方法4、在主方法中让用户注册信息,用User对象记录,然后调用对象的DisplayInfo方法显示注册信息。
class User
{
//定义账号,密码,性别
string login;
string password;
string danger;
//定义账号
public string Login
{
get { return login; }
set
{
//进行判断
if (char.IsLetter(value,0))
{
login = value;
}
else
{
Console.WriteLine("用户名非法,必须以字母开头!");
Console.WriteLine("用户名默认为abc");
login = "abc";
}
}
}
//定义密码
public string Password
{
get { return password; }
set
{
if (value.Length>=8)
{
password = value;
}
else
{
Console.WriteLine("密码长度不安全,密码长度应不小于8位");
Console.WriteLine("密码已经重新默认为11111111,请尽快进行更改!");
password = "11111111";
}
}
}
//定义性别
public string Danger
{
get { return danger; }
set
{
if (value =="男"||value=="女")
{
danger= value;
}
else
{
Console.WriteLine("性别必须为'男'或'女',请重新输入!");
Console.WriteLine("性别默认男,请尽快进行更改!");
danger = "男";
}
}
}
//输出信息方法
public void DisPlayinfo()
{
Console.WriteLine("用户名:{0}", Login);
Console.WriteLine("密码:{0}", password);
Console.WriteLine("性别:{0}", danger);
}
}
#endregion
}
3、属性
什么是属性
- 属性是字段的一种扩展
- 属性(property)是一种用于访问对象或类型的特征的成员,特征反映了状态。
- 属性是字段的自然扩展
- 从命名来看,field更偏向于实例对象在内存中的布局,property更偏向于反映现实世界对象的特征
- 对外:暴露数据,数据可以存在字段里,也是可以动态计算出来的,
- 对内:保护字段不被非法值“污染”
- 属性由Get/Set方法对进化而来
属性的声明
- 完整声明——后台(back)成员变量与访问器(注意使用code snippet和refactor工具)
- 简略声明——只有访问器(查看IL代码)
- 动态计算值的属性
- 注意实例属性和静态属性
- 属性的名字一定是名词
- 只读属性——只有getter没有setter
尽管语法上正确,几乎没有人使用“只读属性”,因为属性的主要目的是通过向外暴露数据而表示对象/类型的状态
属性与字段的关系
- 一般情况下,他们都是用来表示实体(对象或类型)的状态
- 属性大多数情况下是字段的包容器(wrapper)
- 建议:永远使用属性(而不是字段)来暴露数据,即字段永远都是private或者protected的
属性property是一种用于访问对象或类的特征的成员。属性的示例包括字符串的长度、字体的大小、窗口的标题、客户的名称等等。属性是字段的自然扩展,此两者都是具有关联类型的命名成员,而且访问字段和属性的语法是相同的。然而,与字段不同,属性不表示存储位置。相反,属性有访问器(accessor),这些访问器指定在它们的值被读取或写入时需要执行的语句。因此属性提供了一种机制,它把读取和写入对象的某些特征与一些操作相关联起来,甚至它还可以对此类特性进行计算。
using System;
namespace 属性
{
class Program
{
static void Main(string[] args)
{
/*
//计算三个学生的平均年龄
Student stu1 = new Student();
stu1.Age = 20;
Student stu2 = new Student();
stu1.Age = 20;
Student stu3 = new Student();
stu1.Age = 20;
int avgAge = (stu1.Age+stu2.Age+stu3.Age)/3;
Console.WriteLine(avgAge);
Student s1 = new Student();
s1.SetAge(30);
Student s2 = new Student();
s2.SetAge(30);
Student s3 = new Student();
s3.SetAge(30);
//当数值大于120时出现异常
//Student s3 = new Student();
//s3.SetAge(30);
int avgAge1 = (s1.GetAge() + s2.GetAge() + s3.GetAge()) / 3;
Console.WriteLine(avgAge1);
*/
//使用try catch来进行检测
//保护字段的方法
/*
try
{
Student s1 = new Student();
s1.SetAge(30);
Student s2 = new Student();
s2.SetAge(30);
//异常输入,输出Age value has erroe!
Student s3 = new Student();
s3.SetAge(300);
int avgAge1 = (s1.GetAge() + s2.GetAge() + s3.GetAge()) / 3;
Console.WriteLine(avgAge1);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
//使用get和set语句之后可以写回原来的形式,因为有保护措施
try
{
Student s1 = new Student();
s1.Age = 20;
Student s2 = new Student();
s2.Age = 20;
Student s3 = new Student();
s3.Age = 20;
int avgAge2 = (s1.Age + s2.Age+ s3.Age) / 3;
Console.WriteLine(avgAge2);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
*/
Console.ReadKey();
}
}
class Student
{
//public int Age;
//私有字段
private int age;
//使用属性
public int Age
{
get
{
return this.age;
}
set
{
if (value >= 0 && value <= 120)//value在set上下文中是关键字
{
this.age = value;
}
else
{
throw new Exception("Age value has erroe!");
}
}
}
//获取字段的值的方法
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 erroe!");
}
}
}
}
4、什么是索引器
- 索引器(indexer)是这样一种成员:它使对象能够用与数组相同的方式(即使用下标)进行索引
- 索引器的声明
- 注意没有静态索引器
5、什么是常量
- 常量(constant)是表示常量值(即,可以在编译时计算的值)的类成员
- 常量隶属于类型而不是对象,即没有”实例常量“
- 实例常量的角色由只读实例字段来担当
- 主要区分成员常量与局部常量
常量的声明
各种只读的应用场景
- 为了提高程序可读性和执行效率——常量
- 为了防止对象的值被改变——只读字段
- 向外暴露不允许修改的数据——只读属性(静态或非静态),功能与常量有一些重叠
- 当希望成为常量的值其类型不能被常量声明接受时(类/自定义结构体)——静态只读字段
using System;
namespace 索引器和常量
{
class Program
{
static void Main(string[] args)
{
/*
Student stu = new Student();
stu["Math"] = 90;
var mathScore = stu["Math"];
*/
const int x = 100;
Console.WriteLine(MyClass.WebsiteURL);
Console.ReadKey();
}
static double GetArea(double r)
{
double a = Math.PI * r * r;
return a;
}
}
class MyClass
{
public const string WebsiteURL = "http://www.waspec.rog";
public static readonly Building location = new Building("Some Address") { };
}
class Building
{
public Building(string address)
{
this.Address = address;
}
public string Address { get; set; }
}
class Student
{
/*
private Dictionary scoreDictory = new Dictionary();
///
/// 索引器一般用于集合类型
///
///
///
public int? this[string subject]
{
get
{
if (this.scoreDictory.ContainsKey(subject))
{
return this.scoreDictory(subject);
}
else
{
return null;
}
}
set
{
if (value.HasValue==false)
{
throw new Exception("Error");
}
if (this.scoreDictory.ContainsKey(subject))
{
this.scoreDictory(subject) = value.Value;
}
else
{
this.scoreDictory.Add(subject, value.Value);
}
}
}
*/
}
}