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.虽然属性实际上就是方法,但是不允许泛型属性。
posted @ 2007-09-09 11:01  包建强  Views(1175)  Comments(0Edit  收藏  举报