• CLR笔记:9.Property


    属性分两种,无参属性,有参属性,后者又叫索引器(indexer)——VB.NET中相应为默认属性。

    1.无参属性
    CLR支持静态属性,实例属性,抽象属性,虚拟属性,但不能被重载。
    属性在MSIL中生成以下内容:
        get_XX方法,当在属性中定义了get的时候——XX为属性名
        set_XX方法,当在属性中定义了set的时候——XX为属性名
        一个位于原数据中的属性定义。

    属性不能作为out/ref传递给方法,字段则可以。
    如果属性中执行语句过多,要花很多时间,这时候优先选用方法。例如线程同步和Remoting。
    多次访问属性,每次返回的值可能不同;而字段的值每次返回都不会改变。例如System.DateTime属性——MS以后会将其改为方法。

    2.有参属性
    定义,有参属性的get方法可以接受1个或者更多参数,set方法可以接受2个或者更多参数
        ——对比,无参属性get方法无参数,set方法有1个参数。

    C#索引器语法,是对[ ]这个运算符的重载,示例如下:
        public class FailSoftArray
        
    {
            
    int[] a;
            
    public int length;

            
    public FailSoftArray(int length)
            
    {
                a 
    = new int[length];
                
    this.length = length;
            }


            
    public int this[int index]
            
    {
                
    get 
                
    {
                    
    if (index >= 0 & index < length)
                    
    {
                        
    return a[index];
                    }

                    
    else
                        
    throw new ArgumentOutOfRangeException();
                }


                
    set
                
    {
                    
    if (index >= 0 & index < length)
                    
    {
                        a[index] 
    = value;
                    }

                    
    else
                        
    throw new ArgumentOutOfRangeException();
                }

            }

        }


        
    public class TestIndex
        
    {
            
    public TestIndex()
            
    {
                FailSoftArray fs 
    = new FailSoftArray(5);

                
    for (int i = 0; i < 5; i++)
                
    {
                    fs[i] 
    = i * 10;
                }

            }

        }

    索引器是可以重载的,不能在this[]的类型上重载,只能在参数上重载——无参属性不可以重载:
            public int this[int index]
            
    {
                
    set { }
            }


            
    public int this[double index]
            
    {
                
    set { }
            }


    以下索引器重载是不对的,尽管改变了Item,在MSIL中是有不同方法名的两套方法,却具有相同的参数集;但是C#不是按名称引用索引器,而是按参数集。
            [IndexerName("Jeff")]
            
    public String this[bool b]
            
    {
                
    set { }
            }


            [IndexerName(
    "Jax.Bao")]
            
    public Int32 this[bool b]
            
    {
                
    set { }
            }

    CLR不区分无参属性和有参属性,都是生成一对方法和一块元数据:
        get_Item方法,当在属性中定义了get的时候
        set_Item方法,当在属性中定义了set的时候
        一个位于原数据中的属性定义。在MSIL中,有专门用于有参属性的元数据定义表。
    对于索引器,使用get_Item和set_Item这两个默认名称。同时,通过反射查看类型是否有Item属性,来判断该类型是否提供了索引器(Generic.List)。
    但是,C#编程中不会看到Item这一默认属性,在与其它语言交互时,可能需要把Item改为其他的名称,方法如下:
        using System.Runtime.CompilerServices;

        
    public sealed class BitArray
        
    {
            [IndexerName(
    "Bit")]
            
    public bool this[int bitPos]
            
    {
                
    set { }
            }

        }
    于是,MSIL生成get_Bit和set_Bit方法。NET中的String.String类型就是Chars而不是Item。

    索引器语法this[..],是C#团队选择的表示方式,意味着C#只允许在对象的实例上定义索引器。
    CLR支持静态有参属性,但是C#没有提供相关语法

    补充:VB.NET"默认属性"语法
    将C#的索引器示例改造成VB.NET的:将属性声明为Default,并加上参数,只是这里的this不再是关键字,而是一个自定义的属性
    Public Class FailSoftArray

        
    Public length As Integer
        
    Private a(length) As Integer


        
    Public Sub New(ByVal length As Integer)
            
    Me.length = length
        
    End Sub


        
    Default Public Property this(ByVal index As Integer)
            
    Get
                
    If (index >= 0 & index < length) Then
                    
    Return a(index)
                
    Else
                    
    Throw New ArgumentOutOfRangeException()
                
    End If
            
    End Get
            
    Set(ByVal value)
                
    If (index >= 0 & index < length) Then
                    a(index) 
    = value
                
    Else
                    
    Throw New ArgumentOutOfRangeException()
                
    End If
            
    End Set
        
    End Property

    End Class


    Public Class TestIndex
        
    Public Sub New()
            
    Dim fs As FailSoftArray = New FailSoftArray(5)

            
    Dim i As Integer
            
    For i = 1 To 5
                fs(i) 
    = i * 10
            
    Next
        
    End Sub

    End Class


    3.性能
        内联:就是方法下包括全部代码,不需要将部分代码放到额外的调用函数中——消除了运行时与调用相关的开销,代价是编译后方法的代码很庞大。
        内联属性方法,因为其通常包括极少代码,所以编译后代码量更小,执行更快。
        由于JIT调试时期不会内联属性方法,所以属性访问器在Release版本性能要快于Debug版本——字段在两个版本中执行得同样快。

    4.属性访问器的可访问性
        可以get是public的;而set是protected的
        get/set的可访问性是在属性名前声明的
            public String Name  //这里的public决定了get/set默认的可访问性
            {
                
    get return null; }
                
    protected set { }   //这里提升了set的可访问性
            }

    5.虽然属性实际上就是方法,但是不允许泛型属性。
  • 相关阅读:
    App Store 审核指南
    Redis持久化
    PHP扩展高性能日志系统SeasLog简单上手
    Linux下Redis的安装配置
    Windows下Redis的安装
    安装wamp环境 最新完整版
    Git安装配置(完整版)
    Linux下SVN配置
    配置最新版LAMP环境
    Linux下ftp的安装配置
  • 原文地址:https://www.cnblogs.com/Jax/p/887288.html
Copyright © 2020-2023  润新知