一、变量
原文:https://www.runoob.com/csharp/csharp-variables.html
1、介绍
一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。
我们已经讨论了各种数据类型。C# 中提供的基本的值类型大致可以分为以下几类:
类型 | 举例 |
---|---|
整数类型 | sbyte、byte、short、ushort、int、uint、long、ulong 和 char |
浮点型 | float 和 double |
十进制类型 | decimal |
布尔类型 | true 或 false 值,指定的值 |
空类型 | 可为空值的数据类型 |
C# 允许定义其他值类型的变量,比如 enum,也允许定义引用类型变量,比如 class。这些我们将在以后的章节中进行讨论。在本章节中,我们只研究基本变量类型。
2、C# 中的变量定义
C# 中变量定义的语法:
<data_type> <variable_list>;
在这里,data_type 必须是一个有效的 C# 数据类型,可以是 char、int、float、double 或其他用户自定义的数据类型。variable_list 可以由一个或多个用逗号分隔的标识符名称组成。
一些有效的变量定义如下所示:
int i, j, k; char c, ch; float f, salary; double d;
您可以在变量定义时进行初始化:
int i = 100;
3、C# 中的变量初始化
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:
variable_name = value;
变量可以在声明时被初始化(指定一个初始值)。初始化由一个等号后跟一个常量表达式组成,如下所示:
<data_type> <variable_name> = value;
一些实例:
int d = 3, f = 5; /* 初始化 d 和 f. */ byte z = 22; /* 初始化 z. */ double pi = 3.14159; /* 声明 pi 的近似值 */ char x = 'x'; /* 变量 x 的值为 'x' */
4、接受来自用户的值
System 命名空间中的 Console 类提供了一个函数 ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中。
例如:
int num; num = Convert.ToInt32(Console.ReadLine());
函数 Convert.ToInt32() 把用户输入的数据转换为 int 数据类型,因为 Console.ReadLine() 只接受字符串格式的数据。
5、C# 中的 Lvalues 和 Rvalues
C# 中的两种表达式:
-
lvalue:指向内存位置的表达式被称为左值(lvalue)表达式,lvalue 表达式可以出现在赋值语句的左边或右边。
-
rvalue:指的是存储在内存中某些地址的数值,rvalue 表达式可以出现在赋值语句的右边,不能出现在赋值语句的左边。
变量是 lvalue 的,所以可以出现在赋值语句的左边。数值是 rvalue 的,因此不能被赋值,不能出现在赋值语句的左边。下面是一个有效的语句:
int g = 20;
下面是一个无效的语句,会产生编译时错误:
10 = 20;
6、不同类型变量进行运算的问题
double a = 42.29; int b = 4229; int c = a + b; Console.WriteLine("c = {0}",c); Console.ReadKey();
上面这种编程方法是错误的,会出现错误提示:"无法将类型'double'隐式转换为'int'。"
举例说明,当一个精度高的数据类型与一个精度低的数据类型进行运算时,定义运算结果的变量类型必须与精度最高的变量类型相同。这是为了防止在运算过程中造成数据丢失。
下面是正确代码:
double a = 42.29; int b = 4229; double c = a + b; Console.WriteLine("c = {0}",c); Console.ReadKey(); // 能输出运算结果:c = 4271.29
7、静态变量
在 C# 中没有全局变量的概念,所有变量必须由该类的实例进行操作,这样做提升了安全性,但是在某些情况下却显得力不从心。
因此,我们在保存一些类的公共信息时,就会使用静态变量。
static <data_type> <variable_name> = value;
在变量之前加上 static 关键字,即可声明为静态变量。
静态变量必须使用类名来引用,而不能使用类的实例,因为,静态变量不属于任何实例,而是共有的。
静态变量在声明时,如果没有给出初始值或使用前没有赋任何值的话,系统会给他们一个默认值:对于整型数据默认值为0;单精度数据为:0.0f;双精度数据为0.0;布尔型数据为False;引用型数据为null。
using System; namespace TestApplication { class StaticClass { public static int staticNum = 1; // 定义类的静态成员变量 } class Program { static void Main(string[] args) { // 静态成员变量 Console.WriteLine("静态成员staticNum的值是{0}", StaticClass.staticNum); } } }
8、详解变量
类变量(静态属性)
类变量:被static修饰的属性。
作用范围:在类变量定义之后,相当于python的类属性。
生命周期:出生:类加载时,类变量就分配内存空间。死亡:JVM退出。
成员变量(实例变量,属性)
成员变量:在类中定义,成员变量就是类中的属性。当new对象的时候,每个对象都有一份属性。一个对象中的属性就是成员变量。
作用范围:在类内部任何地方都可以访问成员变量,相当于python的对象属性。
声明周期:出生,new对象的时候,开辟内存空间。死亡,堆内存地址没有引用,变成垃圾,被垃圾回收器回收。
局部变量(本地变量)
局部变量:方法的形式参数以及在方法中定义的变量。
作用范围:在方法体重的任何位置都可以访问。
生命周期:出生:运行到创建变量的语句时。死亡:超过了其作用范围。
二、常量
原文:https://www.runoob.com/csharp/csharp-constants.html
常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
常量可以被当作常规的变量,只是它们的值在定义后不能被修改。
1、整数常量
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。
整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。
这里有一些整数常量的实例:
212 /* 合法 */ 215u /* 合法 */ 0xFeeL /* 合法 */ 078 /* 非法:8 不是一个八进制数字 */ 032UU /* 非法:不能重复后缀 */
以下是各种类型的整数常量的实例:
85 /* 十进制 */ 0213 /* 八进制 */ 0x4b /* 十六进制 */ 30 /* int */ 30u /* 无符号 int */ 30l /* long */ 30ul /* 无符号 long */
2、浮点常量
一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
这里有一些浮点常量的实例:
3.14159 /* 合法 */ 314159E-5L /* 合法 */ 510E /* 非法:不完全指数 */ 210f /* 非法:没有小数或指数 */ .e55 /* 非法:缺少整数或小数 */
使用浮点形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。
3、字符常量
字符常量是括在单引号里,例如,'x',且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 'x')、一个转义序列(例如 '\t')或者一个通用字符(例如 '\u02C0')。
在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符 tab(\t)。在这里,列出一些转义序列码:
转义序列 | 含义 |
---|---|
\\ | \ 字符 |
\' | ' 字符 |
\" | " 字符 |
\? | ? 字符 |
\a | Alert 或 bell |
\b | 退格键(Backspace) |
\f | 换页符(Form feed) |
\n | 换行符(Newline) |
\r | 回车 |
\t | 水平制表符 tab |
\v | 垂直制表符 tab |
\ooo | 一到三位的八进制数 |
\xhh . . . | 一个或多个数字的十六进制数 |
以下是一些转义序列字符的实例:
namespace EscapeChar { class Program { static void Main(string[] args) { Console.WriteLine("Hello\tWorld\n\n"); Console.ReadLine(); } } } /* 当上面的代码被编译和执行时,它会产生下列结果: Hello World */
4、字符串常量
字符串常量是括在双引号 "" 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符
使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。
这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。
注意点:字符(char)是单引号,字符串(string)是双引号。
string a = "hello, world"; // hello, world string b = @"hello, world"; // hello, world string c = "hello \t world"; // hello world string d = @"hello \t world"; // hello \t world string e = "Joe said \"Hello\" to me"; // Joe said "Hello" to me string f = @"Joe said ""Hello"" to me"; // Joe said "Hello" to me string g = "\\\\server\\share\\file.txt"; // \\server\share\file.txt string h = @"\\server\share\file.txt"; // \\server\share\file.txt string i = "one\r\ntwo\r\nthree"; string j = @"one two three";
5、定义常量
常量是使用 const 关键字来定义的 。定义一个常量的语法如下:
const <data_type> <constant_name> = value;
下面的代码演示了如何在程序中定义和使用常量:
using System; namespace TestApplication { class SampleClass { public int x; public int y; public const int c1 = 5; public const int c2 = c1 + 5; public SampleClass(int p1, int p2) { x = p1; y = p2; } } public class ConstTest { static void Main(string[] args) { SampleClass mC = new SampleClass(11, 22); Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y); Console.WriteLine("c1 = {0}, c2 = {1}", SampleClass.c1, SampleClass.c2); } } }
当上面的代码被编译和执行时,它会产生下列结果:
x = 11, y = 22
c1 = 5, c2 = 10
由此可见,const 常量的使用跟static静态变量一样,都是使用类名.xxx去引用使用。
6、注意点
1.静态常量(编译时常量)const
在编译时就确定了值,必须在声明时就进行初始化且之后不能进行更改,可在类和方法中定义。
const 的值必须在编译期间就知道,换句话来说,你必须给常量一个初始值并且你不能用一个变量来给常量初始化:
const double a = 3.14;// 正确声明常量的方法 const int b; // 错误,没有初始化 int a = 14; //必须要有初始值 const int b = a; // 报错,不能用一个变量来给常量初始化
2.动态常量(运行时常量)readonly
在运行时确定值,只能在声明时或构造函数中初始化,只能在类中定义。定义方法如下:
class Program { readonly int a = 1; // 声明时初始化 readonly int b; // 构造函数中初始化 Program() { b = 2; } static void Main() { } }
在下面两种情况下:
- 取值永久不变(比如圆周率、一天包含的小时数、地球的半径等)。
- 对程序性能要求非常苛刻。
可以使用 const 常量,除此之外的其他情况都应该优先采用 readonly 常量。
3.关于常量变量命名的规则
带有 private 私有访问修饰符的常量要以骆驼命名法命名,即以下划线开头,第一个单词的首字母小写,余下单词首字母大写。
private const string _bookName = "新华字典";
带有 public 公共修饰符、protected 受保护修饰符等的常量要以帕斯卡命名法命名,即各个单词首字母都要大写。
public const int BookPrice = 10;
7、C#中static、const、readonly与static readonly的区别与联系
原文:https://mp.weixin.qq.com/s/T1foLMKR_6PTSZr5q6KrRQ
1、static修饰符
初始化时机:运行时,可以声明时赋值,也可以在(静态)构造函数或使用时赋值
值状态:允许修改
修饰范围:类、字段、属性、方法、运算符、事件、构造函数(不能用于索引器、析构函数或类以外的类型)
主要应用场景:主要作用于类的公共属性
使用方法:类名.xxx去引用
2、const修饰符
初始化时机:编译时,即编译程序时将值已经嵌入代码中,只能在声明变量的时候赋值
值状态:不允许动态修改
修饰范围:字段、局部变量
主要应用场景:主要应用于程序运行中不需要改变的变量的值,比如数学符号PI
使用方法:类名.xxx去引用
3、readonly修饰符
初始化时机:运行时,可以声明时赋值或在类中的构造函数中赋值
值状态:允许修改,但只能在构造函数中修改
修饰范围:字段
主要应用场景:主要作用于实例化的对象的只读属性
使用方法:对象.xxx去引用
4、static readonly修饰符
初始化时机:运行时,是两个关键字的组合
值状态:允许修改,声明时赋值或者静态构造函数中赋值
修饰范围:字段
主要应用场景:第一,和const相比,它主要应用于引用性变量;而const,只能用于string类型的引用性变量;第二,类的只读公共属性
使用方法:类名.xxx去引用
总结:
const是静态的、编译期变量,只能在声明变量的时候赋值。
readonly是运行时变量,可以在声明的时候或在构造函数内赋值。
static readonly变量就变成了静态的、编译期变量。只能静态构造函数中进行初始化。
同时static readonly可以理解为是最简单的一种单例模式实现方式。
const是静态常量,readonly是动态常量.const高效,readonly灵活!但实际开发中我们经常用static readonly 来代替const, 以平衡const在灵活性上的不足.
using System; namespace TestApplication { class SampleClass { public static int s1 = 1; // static 声明时赋值 public static int s2; public static int s3; public const double PI = 3.14; // const 只能在声明时赋值 public readonly string r1 = "Hello"; // readonly 声明时赋值 public readonly string r2; public static readonly string sr1 = "Hi"; // static readonly 声明时赋值 public static readonly string sr2; public SampleClass(int ss2, string r22) { s2 = ss2; // 构造函数中初始化static变量s2 r2 = r22; // 构造函数中初始化readonly变量r2 } static SampleClass() { s3 = 3; // 静态构造函数中初始化static变量s3 sr2 = "devil"; // 静态构造函数中初始化static readonly变量sr2 } } public class ConstTest { static void Main(string[] args) { SampleClass mC = new SampleClass(2, "world"); Console.WriteLine("static变量: s1 = {0}, s2 = {1}, s3 = {2}", SampleClass.s1, SampleClass.s2, SampleClass.s3); Console.WriteLine("const变量: {0}", SampleClass.PI); Console.WriteLine("readonly变量: r1 = {0}, r2 = {1}", mC.r1, mC.r2); Console.WriteLine("static readonly变量: sr1 = {0}, sr2 = {1}", SampleClass.sr1, SampleClass.sr2); } } }