C#作为强类型语言,变量声明是编写任何程序的第一步。其基本语法可以概括为“数据类型 变量名 = 初始值;”,其中数据类型决定变量能存储什么值,变量名用于在代码中引用该存储位置,等号右侧则是可选的初始化表达式。与JavaScript、Python这些弱类型语言不同,C#不允许在未指定类型的情况下直接使用变量,也不允许在赋值前读取局部变量。理解变量声明的完整规则,是避免编译错误和写出规范代码的基础。

一、显式类型声明:类型与名称必不可少
C#最基本的变量声明语法是:数据类型 变量名;。如果希望在声明的同时赋予初始值,则写作数据类型 变量名 = 初始值;。这里的“数据类型”可以是内置值类型、引用类型或自定义类型,变量名必须是合法的标识符。C#标识符只能由字母、数字和下划线组成,且不能以数字开头,不能包含空格或连字符。例如int count;声明了一个名为count的整数变量,但还没有初始值。
int age = 25; string name = "Alice"; double price = 9.99; bool isActive = true; char grade = 'A';
如果只声明不初始化,可以在后续代码中再赋值,但必须在使用之前完成赋值。C#编译器对局部变量有明确的“必须赋值”检查,若在未赋值时读取变量,会出现编译错误CS0165。例如下面的代码会编译失败:
int total; Console.WriteLine(total); // 编译错误:使用了未赋值的局部变量 total = 100;
同一类型变量可以放在一条语句中同时声明,如int x = 1, y = 2, z = 3;。这种写法适合初始化一组含义相近的变量,但不应过度使用,否则会降低可读性。通常更推荐每个变量单独一行,便于添加注释和调试。
二、var隐式类型声明:让编译器推断类型
C# 3.0引入了var关键字,让变量声明不必显式写出数据类型。使用方式是在初始化表达式中由编译器自动推断类型,例如var number = 10;会被推断为int,var message = "Hello";会被推断为string。var并不是动态类型,编译完成后变量类型仍然是固定的,number不能再被赋值为字符串。
var number = 10; var message = "Hello"; var items = new List<string>(); var ratio = number + 0.5; // 推断为 double
var只能用于局部变量,不能用于类字段或方法参数。声明var变量时必须提供初始值,否则编译器无法推断类型。例如var value = null;会因为null没有具体类型而报错。也不能在同一语句中用var声明多个变量,如var a = 1, b = 2;是非法写法。var适合初始化类型名称很长的对象,例如var dict = new Dictionary<string, List<int>>();,可以让代码更简洁。但如果右侧类型不够直观,显式声明反而更有利于阅读。
三、const与readonly:不可变量声明的两种选择
变量默认可以重新赋值,但在某些场景下需要不可变数据。C#提供const和readonly两个关键字,声明时位置放在数据类型之前。const用于编译时常量,必须声明时初始化为常量表达式,且只能用于值类型、字符串等。例如public const double Pi = 3.14159;。const常量是隐式静态的,可以直接通过类名访问。
class Circle
{
public const double Pi = 3.14159;
public readonly double Radius;
public Circle(double radius)
{
Radius = radius;
}
}
readonly字段可以在声明时赋值,也可以在实例构造函数中赋值,之后不可修改。与const不同的是,readonly可以是实例字段,类型不受限制,可以为引用类型。二者声明语法类似,但语义差异很大:const在编译时会被替换为具体值,readonly则在运行时确定。选择时,如果值在编译前就确定且不依赖实例,用const;如果需要通过构造函数传入,用readonly。
其他修饰符如static、public、private也可以组合声明变量。在类中声明字段时,完整语法可以包含访问修饰符、static、readonly、类型、变量名。例如private static int counter = 0;表示一个私有的静态整数字段,并且初始化为0。
四、作用域与声明位置的影响
变量作用域决定了变量在哪些代码块中可见。C#中的变量必须声明在类型或方法内部,不存在游离于类型之外的全局变量。方法内声明的局部变量只能在声明它的块及其嵌套块中使用,离开块后变量生命周期结束,无法访问。例如在if代码块内声明的变量,在if结束后就不能再使用。
class Program
{
static int total = 0; // 静态字段,属于类型
static void Main()
{
int local = 5; // 局部变量
if (local > 0)
{
int inner = 10;
Console.WriteLine(inner);
}
// Console.WriteLine(inner); // 超出作用域,无法访问
}
}
字段和局部变量的生命周期不同。局部变量存储在栈上,方法执行完毕自动释放;字段存储在堆上,随对象实例存在。静态字段则与类型生命周期一致,在程序启动时初始化。声明位置也会影响命名冲突:在同一作用域内不能声明同名变量,但嵌套块内如果命名与外层局部变量相同,C#编译器会报CS0136错误,不允许遮蔽外层变量,这与C语言不同。
在for、foreach、while等语句的代码块中声明的变量同样只在块内有效。比如for (int i = 0; i < 5; i++)中的i只在该循环内可用。理解作用域有助于减少变量占用内存的时间,也能避免在错误的位置访问变量。
五、变量声明常见错误与规范写法
初学者声明C#变量时最常遇到几类错误:未赋值使用、类型不匹配、var缺少初始化、变量名与关键字冲突。C#内置关键字不能直接作为变量名,如int、class、string都不可以,除非在名称前加@符号,例如int @class = 5;,但这种写法只为兼容其他语言生成的标识符,不建议在普通代码中使用。
// 错误示例 // int 1number; // 标识符不能以数字开头 // string name; Console.WriteLine(name); // 未赋值使用 // var value = null; // var无法推断null类型 // int age = "twenty"; // 类型不匹配
变量命名方面,C#社区普遍采用驼峰命名法给局部变量和参数命名,例如userName、orderCount。字段通常使用下划线前缀或PascalCase,常量使用PascalCase。命名规范不会影响编译,但直接影响代码可读性和团队协作效率。声明变量时尽量使用有意义的名称,避免a、b、temp这类无意义缩写。
变量声明虽然是C#最基础的语法,但它与类型系统、作用域、内存分配以及代码规范紧密相关。建议在编写每一个变量声明时都明确三点:这个变量要存什么类型的数据、初始值是什么、它的可见范围应该有多大。掌握这些基础规则后,后续学习方法、类、集合和泛型时会更顺利。