常量、字段、和方法

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

相关文章

目录简介使用JS互操作使用ClipLazor库创建项目使用方法简单测...
目录简介快速入门安装 NuGet 包实体类User数据库类DbFactory...
本文实现一个简单的配置类,原理比较简单,适用于一些小型项...
C#中Description特性主要用于枚举和属性,方法比较简单,记录...
[TOC] # 原理简介 本文参考[C#/WPF/WinForm/程序实现软件开机...
目录简介获取 HTML 文档解析 HTML 文档测试补充:使用 CSS 选...