CLR Via CSharp读书笔记(10):属性

自动实现的属性

与直接声明一个名为Name的public String字段相比,AIP(Auto Implement Property)意味着创建了一个属性。访问该属性的任何代码实际都会调用get和set方法。以后如果决定自己实现get和/或set方法,访问属性的任何代码都不必重新编译。如果将Name声明为字段,以后又想把它更改为属性,那么访问字段的所有代码都必须重新编译,以便访问属性的方法。

AIP的支持字段(private字段)的名称是有编译器决定的,而且每次重新编译代码,它都可能更改这个名称。在任何想要序列化或反序列化的类型中,都不要使用AIP功能。

注意:如果使用AIP,属性必然是可读和可写的,即编译器会同时生成get和set方法。

合理定义属性

属性不能作为out或ref参数传递给方法;字段却可以。

属性方法可能花费较长时间执行;字段的访问则总是立即完成。如果需要线程同步,就不应该使用属性,它可能造成线程永远终止。这种情况下,最好是使用方法。此外,如果类可以被远程访问,调用属性方法会非常慢,应该优先使用方法而不是属性。

对象和集合初始化器

Employee e = new Employee() { Name = "Jeff", Age = 45 };
Employee e = new Employee { Name = "Jeff", Age = 45 };
var table = new Dictionary<String, Int32>() { { "Jeff", 1 }, { "Kristin", 2 }, { "Adian", 3 } };

Classroom classroom = new Classroom { Students = { "Jeff", "Kristin", "Adian" } };

匿名类型

使用简洁的语法来声明一个不可变(immutable)的元组类型。元组(tuple)类型时含有一组属性的类型,这些属性通常以某种方式相互关联。

class Program
{
    static void Main(string[] args)
    {
        var o1 = new { Name = "Jeff", Year = 1965 }; // 匿名类型

        var people = new[] { // 由于名称的同一性而创建的隐式类型的数组
            o1,
            new { Name = "Kristin", Year = 1970 },
            new { Name = "Adian", Year = 2003 },
            new { Name = "Grant", Year = 2008 }
        };

        Console.WriteLine("Name = {0}, Year = {1}", o1.Name, o1.Year);
    }
}

匿名类型自动生成的属性是只读的,而非可读可写,目的是防止对象的哈希码发生改变。

System.Tuple类型:

所有Tuple类型都实现了IStructuralEquatable, IStructuralComparable和IComparable接口。

class Program
{
    static void Main(string[] args)
    {
        var minmax = Minmax(6, 2);

        Console.WriteLine("Mix = {0}, Max = {1}", minmax.Item1, minmax.Item2);
    }

    private static Tuple<Int32, Int32> Minmax(Int32 a, Int32 b)
    {
        return new Tuple<Int32, Int32>(Math.Min(a, b), Math.Max(a, b));
    }
}

有参属性
有参属性的get访问器方法接受一个或多个参数,set访问器方法接受两个或多个参数。C#语言将有参属性称为索引器,可以将索引器看做重载[]操作符的一种方式。
和无参数型不同,类型可以提供多个重载的索引器,只要这些索引器的签名不同。C#只允许在对象的实例上定义索引器,而没有 提供静态索引器属性的语法,虽然CLR是支持静态有参属性的。
编译器为索引器生成的方法名分别为get_Item和set_Item。类型如果提供了一个名为Item的属性,则可判断该类型提供了一个索引器。可以使用IndexerNameAttribute来重命名索引器属性。

public sealed class BitArray
{
    [IndexerName("Bit")]
    public Int32 this[Int32 bitPos]
    {
        get { return 0; }
    }

    [IndexerName("Bit")]
    public Boolean this[String bitPos]
    {
        get { return true; }
    }
}

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

对于简单的get和set访问器方法,JIT编译器会将代码内联(inline)。这样,使用属性(而不是字段)就没有性能损失。JIT编译器调试时不会内联属性方法。

C#不允许在定义属性时,引入自己的泛型类型参数,因为概念上讲不通。属性本应表示的是一项可供查询或设置的对象特征。一旦引入泛型类型参数,就意味着查询/设置行为发生改变。


 

原文地址:https://www.cnblogs.com/thlzhf/p/2805433.html