第10章 属性

属性允许源代码用一个简化的语法来调用一个方法。

CLR支持两种属性:无参属性 (parameterless property) ,有参属性(parameterful property)

C#中将有参属性称为索引器(indexer)

10.1无参属性

一般用类型的字段成员来实现获取或改变类型的状态信息。

面向对象设计和编程的重要原则之一就是数据封装(data encapsulation),它意味着类型的字段永远不应该公开。强烈建议将所有的字段都设为private。

要允许获取类型状态信息,就公开一个针对该用途的方法。

封装了字段访问的方法通常称为访问器(accessor)方法(如下面的GetName,SetName)。访问器方法可以对数据的合理性进行检查,确保对象的状态不被破坏。

public sealed class Employee

    {

        private String m_Nmae;

        private Int32 m_Age;

        public String GetName()

        {

            return m_Nmae;

        }

        public void SetName(String value)

        {

            m_Nmae = value;

        }

        public Int32 GetAge()

        {

            return m_Age;

        }

        public void SetAge(Int32 value)

        {

            if (value < 0)

            {

                throw new ArgumentOutOfRangeException("value", value.ToString(), "The value must be grater than or equal to 0");

            }

            m_Age = value;

        }

 public static void Main()

        {

            Employee e = new Employee();

            e.SetName("Jeffery Richter");

            String EmployeeName = e.GetName();

            e.SetAge(41);

            e.SetAge(-5);

            Int32 EmployeeAge = e.GetAge();

        }

    }

将SetXxx方法标记为protected,就可以实现只允许派生类型修改值。

以上代码中,类型的用户必须调用方法,而不能直接引用一个字段名。

编程语言和CLR还提供了一种称为属性(property)的机制,如下:

public sealed class Employee

    {

        private String m_Nmae;

        private Int32 m_Age;

        public String Name

        {

            get { return (m_Nmae); }

            set { m_Nmae = value; }

        }

        public Int32 Age

        {

            get { return (m_Age); }

            set

            {

                if (value < 0)

                {

                    throw new ArgumentOutOfRangeException("value", value.ToString(), "The value must be greater than or equal to 0");

                }

                m_Age = value;

            }

        }

        public static void Main()

        {

            Employee e = new Employee();

            e.Name = "Jeffery Richter";

            String EmployeeName = e.Name;

            e.Age = 41;

            e.Age = -5;

            Int32 EmployeeAge = e.Age;

        }

    }

可将属性想象成智能字段(smart field),即背后有额外逻辑的字段。

每个属性都有一个名称(Name,Age)和一个类型(String,Int32不能为void)。属性不能重载。定义属性时,可以省略set方法来定义一个只读属性,或者省略get方法来定义一个只写属性。

通过属性的get和set方法来操作类型内私有的字段,是一种很常见的做法。

以前面的Employee类型为例。编译器编译这个类型时,会发现其中的Name和Age属性。由于两个属性都有get和set访问器方法,所以编译器在Employee类型中生成4个方法定义。

10.1.1自动实现的属性

如果只是为了封装一个支持字段而创建一个属性,C#还提供了更简单的语法,称为自动实现的属性(automatically Implemented Property)。

10.1.2合理定义属性

我个人不喜欢属性

10.1.3对象和集合初始化器

System.Collections命名空间包含可使用的集合类和相关的接口,提供了集合的基本功能。  

IEnumerable 接口

System.Collections

该枚举数支持在非泛型集合上进行简单迭代

所有继承了IEnumerable的类,要使用foreach迭代器时,就需要使用该方法。因此也只有实现了该接口的类才可以使用foreach。

名称

说明

GetEnumerator()

返回循环访问集合的枚举数。

IList 接口

System.Collections

IList 是 ICollection 接口的子代,并且是所有(非???)泛型列表的基接口

IList继承自ICollection

名称

说明

Add(Object)

将某项添加到 IList 中。

Clear()

从 IList 中移除所有项。

Contains(Object)

确定 IList 是否包含特定值。

CopyTo(Array, Int32)

从特定的 Array 索引处开始,将 ICollection 的元素复制到一个 Array 中。(从 ICollection 继承。)

GetEnumerator()

返回循环访问集合的枚举数。(从 IEnumerable 继承。)

IndexOf(Object)

确定 IList 中特定项的索引。

Insert(Int32, Object)

将一个项插入指定索引处的 IList。

Remove(Object)

从 IList 中移除特定对象的第一个匹配项。

RemoveAt(Int32)

移除指定索引处的 IList 项。

ICollection<T> 接口

System.Collections.Generic

定义操作泛型集合的方法。

ICollection继承自IEnumerable

名称

说明

Add(T)

将某项添加到 ICollection<T> 中。

Clear()

从 ICollection<T> 中移除所有项。

Contains(T)

确定 ICollection<T> 是否包含特定值。

CopyTo(T[], Int32)

从特定的 Array 索引开始,将 ICollection<T> 的元素复制到一个 Array 中。

GetEnumerator()

返回一个循环访问集合的枚举器。(从 IEnumerable<T> 继承。)

Remove(T)

从 ICollection<T> 中移除特定对象的第一个匹配项。

ICollection主要针对静态集合;IList主要针对动态集合。

如果一个方法的返回值是IEnumerable<T> ,必须在方法后面使用.ToList()方法才能得到一个集合数据。

集合的初始化被认为是相加(Additive)操作,而非替换的操作。编译器发现Student属性的类型是List<String>,而且这个类型实现了IEnumerable<String>接口。如下:

public sealed class Classroom

{

    private List<String> m_students = new List<String>();

    public List<String> Students { get { return m_students; } }

    public Classroom() { }

    public static void Main()

    {

        Classroom classroom = new Classroom

        {

            Students = { "Chris","Jeff" }

        };

        //Classroom classroom = new Classroom();

        //classroom.Students.Add("Chris");

        //classroom.Students.Add("Jeff");

        foreach (var student in classroom.Students)

            Console.WriteLine(student);

    }

}

10.1.4 匿名类型

10.1.5 System.Tuple类型

10.2 有参属性

重看

原文地址:https://www.cnblogs.com/chrisghb8812/p/5618292.html