• 常量、字段、和方法


    1、常量

    在C#中以下类型是基类型,可用于定义常量:Boolen、Char、Byte、SByte、Int16、Uint16 、Int32、UInt32、Int64、UInt64、Single、Double、Decimal和 String。

    C#也可以定义非基元类型的常量变量,前提是把值设为null:

    using System;
    public sealed class SomeType {
        // SomeType is not a primitive type but C# does allow
        // a constant variable of this type to be set to 'null'.
        public const SomeType Empty = null;
    }

    因为常量不会被改变,所以总是被视为类型定义的一部分,也就是说它被视为静态成员,而不是实例成员。

    常量定义后从不变化的特性有以下需要注意的:

    1、因为不会被改变,代码引用常量符号时,编译器在定义常量的程序集的元数据中查找该符号,提取常量的值,将值嵌入生产的IL代码中。

    2、因为常量值内嵌到IL代码中,所以在运行时不需要分配内存。

    3、又因为常量不需要分配内存,所以不能获取常量的地址,也不能以传递引用的方式传递常量。

    这些限制意味着不能很好地支持跨程序集的版本控制。

     

    2、字段

    字段是一种数据成员,其中容纳了一个值类型的实例或者对一个引用类型的引用。

    CLR 支持类型字段实例字段

    • 类型字段:也就是静态字段,它属于类型对象,容纳字段数据所需的动态内存是在类型对象中分配的,而类型对象是在类型加载到一个AppDomain时创建的。而类型加载到AppDomain中通常是在引用了该类型的任何方法首次进行JIT 编译的时候。

    • 实例字段:非静态字段,它属于类型对象的实例,在一个AppDomain中,类型对象只有一个,而由它构造的实例会有好多。如果是实例字段,容纳字段数据所需的动态内存是在构造类型的实例时分配的。

    下面是字段修饰符的详细说明:

      

    3、方法

    3.1 实例构造器和类(引用类型)

    构造器是将类型的实例初始化为良好状态的特殊方法。

    创建引用类型的实例时:

    • 首先 为实例的数据字段分配内存

    • 然后 初始化对象的附加字段(类型对象指针和同步块索引)

    • 最后 调用类型的实例构造器来设置对象的初始化状态

    引用类型的实例构造器又以下特点:

    • 构造引用类型的对象时,没有被构造器显示重写的所有字段都默认为0或者null。

    • 由于永远不能继承实例构造器,所以实例构造器不能使用以下修饰符:virtual, new, override, sealed,or abstract。

    • 如果没有显示的定义任何构造器,C#编译器将定义一个默认构造器,在它的实现中,只是调用了基类的无参构造器。

    • 一个类型可以定义多个实例构造器,每个构造器必须有不同的签名,而且每个都可以有不同的访问性。

    • 类的实例构造器在访问从基类继承的任何字段之前,必须先调用基类的构造器。

    • 极少数时候可以在不调用实例构造器的前提下创建类型的实例。一个是调用Object 的 MemberwiseClone方法。另一个是是反序列化代码使用System.Runtime.Serialization.FormatterServices 类型的GetUninitializedObject 或者GetSageUninitializedObject 方法为对象分配内存,期间不会调用一个构造器。

     

    3.2 实例构造器和结构(值类型)

    CLR 总是允许创建值类型的实例,并且没有办法阻止值类型的实例化。

    值类型构造器的特点:

    • 值类型并不需要定义构造器,C#编译器不会为值类型内联默认的无参构造器。

    • 但CLR确实允许值类型定义构造器,但是必须显示调用才会执行。即便值类型提供了构造器,许多编程器也永远不会自动生成这样的代码。

    • 还有C#编译器不允许值类型定义无参构造器。

    • 为了生成”可验证“代码,在访问值类型的任何字段之前,都需要对全部字段进行赋值。

    // C# allows value types to have constructors that take parameters.
    public SomeValType(Int32 x) {
        // Looks strange but compiles fine and initializes all fields to 0/null.
        this = new SomeValType();
        m_x = x; // Overwrite m_x's 0 with x
        // Notice that m_y was initialized to 0.
    }
    • 在值类型构造器中,this 代表值类型本身的一个实例,用new 创建的值类型的一个实例可以赋值给this。在new 的过程中,会将所有字段设置为零。

     

    3.3 类型构造器

    CLR 支持类型构造器,也称为静态构造器(static constructors )、类型构造器(class constructors )、或者类型初始化器(type initializers )。类型构造器可应用于接口(C#编译器不允许)、引用类型、和值类型。

    类型构造器特点:

    • 实例构造器是设置类型实例的初始化状态。对应地,类型构造器的作用是设置类型的初始化状态。

    • 类型默认没有构造器,如果定义,也只能定义一个。

    • 类型构造器永远没有参数。

    internal sealed class SomeRefType {
        static SomeRefType() {
            // This executes the first time a SomeRefType is    accessed.
        }
    }
    internal struct SomeValType {
    // C# does allow value types to define parameterless type constructors.
        static SomeValType() {
            // This executes the first time a SomeValType is accessed.
        }
    }
    • 虽然C#不允许值类型为它的实例字段使用内联字段初始化语法,但可以为静态字段使用。换句话说,如果将下面定义的SomeType类型从class 改为struct ,那么代码也能编译通过。

    internal sealed class SomeType {
        private static Int32 s_x = 5;
    }

    生成上述代码时,编译器自动为SomeType 生成一个类型构造器:

    internal sealed class SomeType {
        private static Int32 s_x;
        static SomeType() { s_x = 5; }
    }
    • 类型构造器不应调用基类型的类型构造器。因为类型不可能有静态字段是从基类型分享或继承的。

     

    4、扩展方法

    学习扩展方法 的做好方式就是从例子中学习。扩展方法要定义在静态类中,并且在方法的第一个参数前 添加 this 关键字,第一个参数的类型和当前用于调用方法的那个表达式的类型匹配。

    当编译器看到上面的代码时,就会先检查 StringBuilder 类或者它的任何基类是否提供了获取单个Char 参数、名为 IndexOf 的一个实例方法。如果是,就生成 IL 代码来调用它。如果灭有找到匹配的实例方法,就继续检查是否有任何静态类定义了名为 IndexOf 的静态方法,方法的第一个参数的类型和当前调用方法的那个表达式的类型匹配,而其该类型必须用 this 关键字标识。

    扩展方法的原则: (这里只提几个重要的原则)

    • C# 只支持扩展方法,不支持扩展属性、扩展事件、扩展操作符等。

    • 扩展方法(第一个参数前面有 this 的方法) 必须在非泛型的静态类型中声明。类型名没有限制,随便叫什么名字。至少有一个参数,而且只有第一个参数能用 this 关键字标记。

    • 多个静态类可以定义相同的扩展方法。扩展方法所在的静态类必须具有文件作用域(不能嵌套在另一个类中)。

    • 用一个扩展方法扩展一个类型时,同时也扩展了派生类型。

    注意: 由于扩展方法实际是对一个静态方法的调用,所以CLR 不会生成代码对调用方法的表达式的值进行 null 值检查(不保证它非空)。扩展方法式 Microsoft 的 LINQ 技术的基础。

    ExtensionAttribute 类 在C# 中一旦用this 关键字 标记了某个静态方法的第一个参数,编译器就会在内部向该方法应用一个定制特性。该特性会在最终生成的文件的数据中持久性的存储下来。 除此之外,任何静态类只要包含至少一个扩展方法,它的元数据中也会应用这个特性。类似地,任何程序集只要包含了至少一个符合上述特点的静态类,它的元数据中也会应用这个特性。

     

  • 相关阅读:
    数据库
    HTTP请求(Request)和回应(Response)对象
    [Uliweb]-URL映射
    git生成Key操作保存到GITHUB中
    SQL中char、varchar、nvarchar的区别
    Uliweb之 ORM基本使用(Sqlalchemy)
    ORM查询
    CentOS更改ssh端口
    django static文件的引入方式
    Redis持久化策略(RDB &AOF)
  • 原文地址:https://www.cnblogs.com/mingjie-c/p/11638281.html
Copyright © 2020-2023  润新知