1.1 变量的声明
C#中变量的声明我们以实例来说明,例如,int i; 该句声明了一个 int (整型) 变量 i 。再如,string str; 这句声明了一个string(字符串类型)的
变量 str 。
1.2 变量初始化
C#编译器需要每个变量在有了初始值之后才能使用该变量。
在C#变量初始化时有两点需要注意,
A 、变量是类或者结构中的字段,如果没有显式的初始化,在默认状态下,创建这些变量时,其初始值就是0;例如下面的代码:
using System;
namespace gosoa.com
{
class MyFirstClass
{
static int y;
static void Main()
{
Console.WriteLine(y);
}
}
}
我们在类中声明了一个变量y,然后输出该变量,编译并运行后我们会看到输出的结果是0 。
B、方法中的变量,必须显式的初始化,否则在使用该变量的时候会出错。如下面的代码:在编译的时候就会报错。我们需要把int y ; 显式的初始化
,才会通过编译。比如我们初始化y的值为10 ,即 int y=10; 便会通过编译。
using System;
namespace gosoa.com
{
class MyFirstClass
{
static void Main()
{
int y;
Console.WriteLine(y);
}
}
}
对于静态常量(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来定义常量的时候,在类型上有很多限制。首先,此类型必须属于值类型,同时此类型的初始化不能通过new来完成,因此一些用struct定义的值类型常量也不能用const来定义。
相对于const而言,用readonly来定义常量要灵活的多,它的书写方式如下:
public readonly int MAX_VALUE = 10;
为什么称为动态变量,因为系统要为readonly所定义的常量分配空间,即和类的其他成员一样拥有独立的空间。此外,readonly所定义的常量除了在定义的时候可以设定常量值外,还可以在类的构造函数中进行设定。由于readonly所定义的常量相当于类的成员,因此使用const来定义常量所受到的类型限制,在使用readonly去定义的时候全部消失,即可以用readonly去定义任何类型的常量。
综合上面所述,至于对比两者之间的区别具体如下。
静态常量(Compile-time constant)
|
动态常量(Runtime constant)
|
|
定义
|
声明的同时要设置常量值。
|
声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置。
|
类型限制
|
首先类型必须属于值类型范围,且其值不能通过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去定义常量。
变量的作用域是指可以使用该变量的代码区域。一般情况下,确定作用域有如下规则。
A、 只要变量所属的类在某个作用域内,其字段(也叫做 成员变量)也在该作用域中。
B、 局部变量存在于声明该变量的块语句或方法结束的大括号之前的作用域。
在变量使用中,可能产生命名冲突的情况,首先,我们来看下局部变量的作用域冲突。如下代码示例:
using System;
namespace gosoa.com
{
class MyFirstClass
{
static void Main()
{
for(int i=0;i<10;i++)
{
Console.WriteLine(i);
}
for(int i=0;i<20;i++)
{
Console.WriteLine(i);
}
}
}
}
两个循环中都使用了i ,但都可以正常输出,因为每个i的作用域都在其对应的两个循环体内。
再看下例代码:
using System;
namespace gosoa.com
{
class MyFirstClass
{
static void Main()
{
int j=5;
for(int i=0;i<10;i++)
{
int j=20;
Console.WriteLine(i+j);
}
}
}
}
这段代码编译就会出错,因为第一个j 在作用域是整个Main()方法,这样,其在循环体内也是有效的。于是,在循环体内定义一个同名的j时,就会报错了。
我们再看如下示例代码,
using System;
namespace gosoa.com
{
class MyFirstClass
{
int j=30;
static void Main()
{
int j=20;
int i=5;
Console.WriteLine(i+j);
}
}
}
在这段代码中,第一个j的作用域是整个类,也就是类的字段,第二个j的声明会替代第一个j,所以该程序会输出25.
1.4 常量
在声明变量时,在变量前面加上const 关键字就可以把该变量指定为一个常量。
在这里需要注意几点,
A 常量必须在声明的时候就初始化,而且其赋值后就不能再更改了。
B 常量总是静态(static)的,不必在声明常量时添加static关键字。
css添加网格背景
获取bing必应图片
JavaScript超过一定高度导航添加类名
6行css就可以解决的瀑布流布局的方法
css实现背景图横向滚动
JavaScript根据一个元素的显示隐藏控制另一个元素的显示和隐藏
JavaScript判断地址栏链接与导航栏链接是否一致并给导航添加class
JavaScript实现选中文字自动复制
Day 74 算法基础(二)
- 最新文章
-
浏览器重绘与重排的区别?
浮动 清除浮动 float clear
inline-block
标准盒模型-怪异盒模型
脑图——CSS 技术栈
脑图——redux 流程图
获取所有的 CSS 标准
知识的完备性、连贯性很重要
POST 与 PUT 的区别
iOS-Swift协议中关联类型的使用
- 热门文章
-
iOS
iOS 导航控制器A->B push过程中B显示A内容
iOS 审核 reject 总结
Invalid Region <center:+114.18215500, +22.29864800 span:+2.00000000, +2.00000000>
iOS 之 pt、ppi、px、
Swift2.0 -> Swift3.0 改动集锦
'(QQApiObject!) -> SendMessageToQQReq' is not convertible to '(QQApiObject!) -> SendMessageToQQReq! 2017-03-24全网独家
invalid image path
http,https
css nth-child 选择器的使用