• <NET CLR via c# 第4版>笔记 第10章 属性


    10.1 无参属性

    10.1.1 自动实现的属性

    10.1.2 合理定义属性

    • 属性可以只读或只写,而字段访问总是可读和可写的(一个例外是 readonly 字段仅在构造器中可写).
    • 属性方法可能抛出异常;字段访问永远不会.
    • 属性不能作为 out 或 ref 参数传给方法,而字段可以.
    • 属性方法可能花较长时间执行,字段访问则总是立即完成.线程同步不要使用属性,而用方法.从MashalByRefObject派生的类永远都不应该使用属性.
    • 连续多次调用,属性方法每次都可能返回不同的值,字段则每次都返回相同的值.
    • 属性方法可能造成明显的副作用(不同的赋值顺序,可能会出现不同的行为),字段访问则永远不会.
    • 属性方法可能需要额外的内存,或者返回的引用并非指向对象状态一部分,造成对返回对象的修改作用不到原始对象身上.

    10.1.3 对象和集合初始化器

        String s= new Employee (){ Name="Jeff", Age=45 }.ToString().ToUpper();
        //如果想调用的本来就是一个无参构造器,c#还允许省略起始大括号之前的圆括号.
        String s= new Employee { Name="Jeff", Age=45 }.ToString().ToUpper();
    

    10.1.4 匿名类型

        var o1=new{ Name="Jeff", Year=1964};
        Console.WriteLine("Name={0},Year={1}",o1.Name,o1.Year);
    
        //或
        String Name="Grant";
        DateTime dt= DateTime.Now;
        //有两个属性的一个匿名类型
        //1.String Name 属性设为"Grant"
        //2.Int32 Year 属性设为dt中的年份
        var o2 = new { Name, dt.Year };
        Console.WriteLine("Name={0},Year={1}",o2.Name,o2.Year);
    
    • 如果源代码中定义了多个匿名类型,且这些类型具有相同的结构,编译器只会创建一个匿名类型定义,但创建该类型的多个实例.o1=o2
    • 匿名类型的实例不能泄露到方法外部.
    • 方法原型不能接受匿名类型的参数.
    • 方法不能返回匿名类型的引用.

    10.1.5 System.Tuple类型

        //Tuple没啥好写的,还是写写dynamic吧
        dynamic e = new System.Dynamic.ExpandoObject();
        e.x = 6;        //添加一个Int32 'x'属性,其值为6
        e.y = "Jeff";   //添加一个String 'y'属性,其值为"Jeff"
        e.z = null;     //添加一个Object 'z'属性,其值为null
    
        //查看所有属性及其值:
        foreach (var v in (IDictionary<String, Object>)e)
            Console.WriteLine("key={0},v={1}", v.Key, v.Value);
    

    10.2 有参属性(c#称为索引器)

        public sealed class BitArray
        {
            //容纳了二进制位的私有字节数组
            private byte[] m_byteArray;
            private int m_numBits;
    
            //下面的构造器用于分配字节数组,并将所有位设为0
            public BitArray(int numBits)
            {
                //先验证实参
                if (numBits <= 0)
                    throw new ArgumentOutOfRangeException(nameof(numBits));
    
                //保存位的个数
                m_numBits = numBits;
                //为位数组分配字节
                m_byteArray = new byte[(numBits + 7) / 8];
            }
    
            //下面是索引器(有参属性)
            public bool this[int bitPos]
            {
                //下面是索引器的get访问器方法
                get
                {
                    //先验证实参
                    if ((bitPos < 0) || (bitPos >= m_numBits))
                        throw new ArgumentOutOfRangeException(nameof(bitPos));
    
                    //返回指定索引处的位的状态
                    return (m_byteArray[bitPos / 8] & (1 << (bitPos % 8))) != 0;
                }
    
                //下面是索引器的set访问器方法
                set
                {
                    if ((bitPos < 0) || (bitPos >= m_numBits))
                        throw new ArgumentOutOfRangeException(nameof(bitPos), bitPos.ToString());
    
                    if (value)
                    {
                        //将指定索引处的位设为true
                        m_byteArray[bitPos / 8] = (byte)(m_byteArray[bitPos / 8] | (1 << (bitPos % 8)));
                    }
                    else
                    {
                        //将指定索引处的位设为false
                        m_byteArray[bitPos / 8] = (byte)(m_byteArray[bitPos / 8] & ~(1 << (bitPos % 8)));
                    }
                }
            }
        }
    

    BitArray类的索引器用起来很简单:

    //分配含14个位的BitArray数组
    BitArray ba = new BitArray(14);
    
    //调用set访问器方法,将编号为偶数的所有位都设为true
    for (int x = 0;x < 14; x++){
        ba[x]=(x % 2 == 0);
    }
    
    //调用get访问器方法显示所有位的状态
    for (int x = 0; x < 14; x++){
        Console.WriteLine("Bit " + x + " is " +(ba[x] ? "On" : "Off"));
    }
    
    • 可以通过IndexerNameAttribute特性改变编译器使用的索引器名称(默认为Item,并在前面加get_或set_前缀).System.String改变索引器名称为 Chars .
    • c#允许一个类型定义多个索引器,只要索引器的参数集不同.
    • 对于支持多个有参属性的编程语言,必须选中一个有参属性,通过DefaultMemberAttribute特性来标识.这是C#代码唯一能访问的有参属性.

    10.3 调用属性访问器方法时的性能

    • 对于简单的get和set访问器方法,JIT编译器会将代码内联(inline,或者说嵌入).

    10.4 属性访问器的可访问性

    // ⑴
    public class SomeType{
        private string m_name;
        public string Name {
            get { return m_name; }
            // ⑵
            protected set { m_name = value; }
        }
    }
    
    • ⑴ 必须为属性本身指定限制最小的可访问性
    • ⑵ 两个访问器只能选择一个来使用限制较大的

    返回目录

  • 相关阅读:
    nginx原理及常用配置
    课程作业03-1
    Java动手动脑02
    Java课程作业02
    java课堂测试2
    Java验证码程序
    课程作业02-2
    课程作业02-1
    课程作业01
    《大道至简》第一章伪代码
  • 原文地址:https://www.cnblogs.com/harry-wang/p/6868374.html
Copyright © 2020-2023  润新知