zoukankan      html  css  js  c++  java
  • 变量、常量和类型

    变量、常量和类型

    变量

    变量其实是一个点位符,它引用了一块内存地址,但它存储的值是可以变化的。

    变量声明

    单个变量声明:string yourName;
    多个相同类型变量声明: string x, y, z;
    多个不同类型变量声明:

    string x, y;
    double z;
    

    在声明时可以进行初始化: string yourName = “eric”;
    声明时可以选择性地初始化:string x = “x”, y, z;

    变量初始化

    变量初始化时的一些要求

    • 所有的局部变量在被显式地初始化之前,如果使用它则会被编译器抛出编译异常
    • 所有字段级变量被编译器初始化为所属类型中的默认值

    变量的作用域

    • 类的字段所处的作用域等同于该字段所属类所在的作用域
    • 局部变量的作用域仅限于声明它的方法或循环体内部,以大括号{}为界

    作用域重叠

    • 同一个作用域内,存在两个同名的变量,这里不关心变量的类型是否相同。如果存在这种情况,编译器将会报错,编译将无法继续。
    • 局部变量和字段级变量同名,那么局部变量会将同名的字段级变量隐藏,就是说局部变量的作用域内,局部变量的值覆盖了字段级变量的值。

    常量

    • 在声明时立即初始化,其值在初始化后将无法再进行更改
    • 使用显式类型声明,不能使用关键字var
    • 可以在类、结构、接口中进行声明
    • 可以作为类、结构、接口的字段,也可以是定义在类、结构中的方法内部的局部变量,事实上常量永远是静态的,虽然并没有使用static关键字(也不允许)
    • 无法接受变量的赋值,哪怕该变量是static并且是readonly也不行,在初始化时只能使用另一个常量为它赋值,当然直接赋予一个具体的值更好

    静态常量和动态常量的区别

    本小节内容转载自 [静态常量和动态常量区别](https://www.cnblogs.com/yuhuameng/p/5234872.html “静态常量和动态常量区别”)

    在C#中定义常量的方式有两种:

    • 静态常量(Compile-time constant)
    • 动态常量(Runtime constant)

    前者用“const”来定义,后者用“readonly”来定义。 对于静态常量(Compile-time constant),它的书写方式如下:

    public const int MAX_VALUE = 10;

    为什么称它为静态常量呢,因为如上声明可以按照如下理解(注意:如下书写是错误的,会出编译错误,这里只是为了方便说明)。

    public static const int MAX_VALUE = 10;

    用const定义的常量,对于所有类对象而言都是一样的,因此需要像访问静态成员那样去访问const定义的常量,而用对象的成员方式去访问会出编译错误。此外,对于静态常量的访问在编译的时候,是用常量的值去替换常量,例如:

    int nValue = MAX_VALUE;

    这句在编译之后,和如下这句所产生的中间语言代码是一样的。

    int nValue = 10;

    不过,在用const来定义常量的时候,在类型上有很多限制。首先,此类型必须属于简单的数据类型(内建的int和浮点型、枚举或字符串),同时此类型的初始化不能通过new来完成,因此一些用struct定义的值类型常量也不能用const来定义。

    相对于const而言,用readonly来定义常量要灵活的多,它的书写方式如下:

    public readonly int MAX_VALUE = 10;

    为什么称为动态变量,因为系统要为readonly所定义的常量分配空间,即和类的其他成员一样拥有独立的空间。此外,readonly所定义的常量除了在定义的时候可以设定常量值外,还可以在类的构造函数中进行设定。由于readonly所定义的常量相当于类的成员,因此使用const来定义常量所受到的类型限制,在使用readonly去定义的时候全部消失,即可以用readonly去定义任何类型的常量。 综合上面所述,至于对比两者之间的区别具体如下。

    readonly常量只能声明为类字段,支持实例类型或静态类型,可以在声明的同时初始化或者在构造函数中进行初始化,初始化完成后便无法更改。 const常量除了可以声明为类字段之外,还可以声明为方法中的局部常量,默认为静态类型(无需用static修饰,否则将导致编译错误),但必须在声明的同时完成初始化。
    两者的比较

    静态常量 动态常量
    定义 声明的同时要设置常量值 声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置
    类型限制 首先类型必须属于值类型范围,且其值不能通过new来进行设置 没有限制,可以用它定义任何类型的常量。对于类对象而言 对于所有类的对象而言,常量的值是一样的。 对于类的不同对象而言,常量的值可以是不一样的。
    内存消耗 要分配内存,保存常量实体
    综述 性能要略高,无内存开销,但是限制颇多,不灵活 灵活,方便,但是性能略低,且有内存开销

    对于在定义常量的时候,到底是用const来定义还是readonly来定义,我以前为了追求性能,因此尽量用const来定义。但是在此书中,提到了一个关于使用const会产生潜在的bug。就是在程序中使用DLL类库某个类的静态常量时,如果在类库中修改静态常量的值,其它接口没有发生变化,一般来说,程序调用端是不需要重新编译,直接执行就可以调用新的类库。不过就是在此情况下,会产生潜在的bug。这是由于静态常量在编译的时候,是用它的值去替换常量,因此在调用端的程序也是这样进行替换的。例如:在类库中定义了一个静态常量,如下:

    public const int MAX_VALUE = 10;

    那么对于程序中调用此静态常量这段代码,在编译后产生的中间语言代码中,是用10来进行替换,即使用静态常量的地方,改为10了。 那么当类库的静态变量发生变化后,例如:

    public const int MAX_VALUE = 15;

    那么对于调用端程序是可以在没有重新编译的情况下进行运行,不过此时程序的中间语言代码对应于静态变量的值是10,而不是新类库中的15。因此这样产生的不一致,程序会引发潜在的bug。解决此类问题的方法,就是调用端程序在更新类库之后重新编译一下,即生成新的中间语言代码。

    对于如上在const定义常量时所存在的潜在bug,在用readonly定义常量时是不会发生的。因为readonly定义的常量类似于类的成员,因此在访问的时候需要根据具体常量地址来访问,从而避免此类bug。

    鉴于此,建议用readonly来替换const去定义常量。

    数据类型

    C#中的内置类型有bool, byte, sbyte, char, decimal, double, float, int, uint, long, ulong, object, short, ushort, string, 分为值类型(也称为简单类型)和引用类型

    值类型

    结构类型、数值型(整型(sbyte, byte, char, short, ushort, int, uint, long, uling)、浮点型(float, double),十进制型(decimal))、布尔型(bool)和自定义结构类型和枚举类型

    整数初始化时, 如果整数没有后缀, 则其类型为以下类型中可表示其值的第一个类型:int, uint, long, ulong, 同时可以根据后缀进行指定, L或l表示, 再根据实际大小来确定是long还是ulong, U或u表示, 根据实际大小, 判断其类型是uint还是ulong, 如果用UL以其组合, 则表示ulong

    浮点数初始化时, 小数默认被视为double, double myDouble = 2.3; 若希望整数被视为double, 使用后缀d或D, double x = 10d; 如希望实数被视为decimal类型, 使用后缀m或M, decimal myMoney = 1023.5m; 如希望被视为float, 使用后缀f或F, float y = 3.14F;

    后缀中有大写和小写, 但推荐使用大写, 毕竟小写的L容易与1混淆

    引用类型

    引用类型的变量存储在托管栈中,而实际的数据存储在托管堆中, 主要由接口、数组、Object类型、类、委托、字符串、null类型构成, 另外还有指针类型(只能在unsafe标记的上下文中使用)、dynamic类型(大多数情况下与object相同, 不同在于编译器对于dynamic类型的表达式不做进一步解析和类型检查, 实际上会被编译成object, 因此只存在于编译期, 在运行时并不存在)

    参考引用

    [1]: [静态常量和动态常量区别](https://www.cnblogs.com/yuhuameng/p/5234872.html “静态常量和动态常量区别”)

  • 相关阅读:
    Sprinig.net 双向绑定 Bidirectional data binding and data model management 和 UpdatePanel
    Memcached是什么
    Spring.net 网络示例 codeproject
    jquery.modalbox.show 插件
    UVA 639 Don't Get Rooked
    UVA 539 The Settlers of Catan
    UVA 301 Transportation
    UVA 331 Mapping the Swaps
    UVA 216 Getting in Line
    UVA 10344 23 out of 5
  • 原文地址:https://www.cnblogs.com/home-wang/p/10943092.html
Copyright © 2011-2022 走看看