返回题库高级 .NET 刷题C# 选择题 · 第 1 / 50 篇

C# 试题 01:变量、常量与类型推断

0001 以下代码中 x 的类型是什么?

难度: 进阶

var x = flag ? 1 : 2.0;

Console.WriteLine(x.GetType());
  • A. int
  • B. double,条件表达式的两个分支统一为 double
  • C. long
  • D. 编译失败,var 无法推断
查看答案与解析

正确答案B

解析: 条件表达式要求两个分支可统一到同一类型,int 可隐式转换为 double,因此结果为 double;即使 flag 为真,运行时也是装箱为 double 的值。

关键点: 类型统一发生在编译期,var 拿到的是统一后的类型。

0002 以下哪些声明能通过编译?

难度: 进阶

var a = default(int);     // 1
var b = default;          // 2
var c = null;             // 3
var d = (object)null;     // 4
  • A. 只有第 1 项
  • B. 第 1 项和第 4 项
  • C. 全部
  • D. 只有第 2 项
查看答案与解析

正确答案B

解析: default(int) 有明确类型,(object)null 也有目标类型;default 字面量和 null 都没有可供 var 推断的具体类型,编译失败。

关键点: var 需要初始化表达式提供唯一静态类型。

0003 以下代码输出什么?

难度: 进阶

class Config
{
    public static int a = b + 1;
    public static int b = 10;
}

Console.WriteLine($"{Config.a},{Config.b}");
  • A. 1,10,静态字段按文本顺序初始化,a 初始化时 b 还是 0
  • B. 10,10
  • C. 11,10
  • D. 编译失败
查看答案与解析

正确答案A

解析: 静态字段初始化按声明顺序执行:a = b + 1 先执行,此时 b 仍为默认值 0,所以 a = 1;随后 b = 10

关键点: 静态初始化顺序是“文本顺序”,不要依赖未初始化字段。

0004 关于 vardynamic,哪项说法正确?

难度: 进阶

  • A. var 在编译期完成类型决议并参与重载决议;dynamic 在运行时决议,依赖静态决议的特性(如扩展方法)无法直接用于 dynamic
  • B. 两者等价,只是写法不同
  • C. dynamic 在编译期做完整类型检查
  • D. var 是运行时类型,dynamic 是编译期类型
查看答案与解析

正确答案A

解析: var 编译后与显式类型无异,正常参与重载决议和扩展方法查找;dynamic 的所有成员访问在运行时绑定,扩展方法这类静态机制不会参与,调用不存在的方法会抛 RuntimeBinderException

关键点: dynamic 是有意放弃编译期检查,不是 var 的等价物。

0005 以下代码能否通过编译?

难度: 进阶

for (int i = 0; i < 3; i++) { }
for (int i = 0; i < 3; i++) { }
int i = 10;
  • A. 不能,i 重复声明
  • B. 能,循环变量的作用域限定在各自的 for 语句内,与后面的 i 互不冲突
  • C. 不能,第三个 i 与前面冲突
  • D. 只有第一个循环能编译
查看答案与解析

正确答案B

解析: for 头部声明的变量作用域是整个 for 语句,两个循环和后续声明处于互不重叠的作用域,全部合法。

关键点: 作用域按声明位置计算,而不是按方法整体计算。

0006 目标类型 new(C# 9+)中,哪一行无法编译?

难度: 进阶

Dictionary<string, List<int>> map = new()      // 1
{
    ["a"] = new()                              // 2
};

List<int>? maybe = new();                      // 3
var x = new();                                 // 4
  • A. 第 1 行
  • B. 第 2 行
  • C. 第 4 行,var 不提供目标类型
  • D. 第 3 行,可空引用类型注解下 new() 不可用
查看答案与解析

正确答案C

解析: 第 1、2 行分别以 Dictionary<...>List<int> 为目标类型,第 3 行目标类型是 List<int>(可空注解不改变底层类型);var x = new() 没有目标类型,编译失败。

关键点: 目标类型 new 只认“底层类型”,可空注解不影响。

0007 以下代码哪一项能通过编译?

难度: 实战

const int A = int.MaxValue + 1;            // 1
const int B = unchecked(int.MaxValue + 1); // 2
  • A. 第 1 项
  • B. 第 2 项,常量表达式默认按 checked 检查,unchecked 允许溢出回绕为 int.MinValue
  • C. 两项都能编译
  • D. 两项都不能编译
查看答案与解析

正确答案B

解析: 常量表达式即使在不开启全局 checked 的项目里也默认按 checked 语义求值,int.MaxValue + 1 报 CS0220;包在 unchecked 中后允许回绕,B 等于 int.MinValue

关键点: 运行时算术默认 unchecked,常量表达式默认 checked。

0008 关于 conststatic readonly 的跨程序集行为,哪项正确?

难度: 实战

  • A. 修改 const 后,引用程序集在运行时自动读到新值
  • B. const 在编译期嵌入引用方,修改后必须重新编译所有引用程序集;static readonly 无此问题
  • C. const 在运行时通过元数据解析
  • D. 只有 publicconst 会被嵌入
查看答案与解析

正确答案B

解析: const 的值在编译期被复制进引用方的 IL,更新定义方后不重编译引用方会继续使用旧值;static readonly 在类型初始化时读取,引用方无需重编译。

关键点: 公开 API 中对外契约的值用 static readonly 更安全。

0009 以下代码能否通过编译?

难度: 实战

struct Point
{
    public int X;
}

class Holder
{
    private readonly Point _p;

    public void Move() => _p.X = 1;
}
  • A. 不能,readonly 字段是结构体时,其成员不能在构造函数之外修改(CS1648)
  • B. 能
  • C. 能编译,但运行抛异常
  • D. 不能,结构体不允许公开字段
查看答案与解析

正确答案A

解析:readonly 结构体字段修改成员会报 CS1648;这一点与引用类型字段不同——引用类型 readonly 只锁引用,结构体 readonly 连成员写入也禁止。

关键点: readonly 对值类型字段比对引用类型字段约束更强。

0010 以下代码中哪个方法能通过编译?

难度: 进阶

class Holder
{
    private readonly StringBuilder _sb = new();

    public void Clear() => _sb.Clear();              // 1
    public void Swap() => _sb = new StringBuilder(); // 2
}
  • A. 两个都能
  • B. 两个都不能
  • C. 第 1 个能(引用不可变,对象内容可变),第 2 个不能(CS0191)
  • D. 第 1 个不能,第 2 个能
查看答案与解析

正确答案C

解析: readonly 只禁止字段引用被重新赋值;调用引用对象上的方法修改其内部状态是允许的,_sb = ... 则违反只读约束。

关键点: readonly ≠ 深度不可变。

0011 以下代码能否通过编译?

难度: 进阶

int x;
while (flag)
{
    x = 1;
}
Console.WriteLine(x);
  • A. 能
  • B. 不能,循环体可能一次都不执行,x 未确定赋值(CS0165)
  • C. 能,但输出 0
  • D. 能编译,运行抛异常
查看答案与解析

正确答案B

解析: while 循环体可能不执行,确定赋值分析不会假定循环至少进入一次,读取 x 报 CS0165。

关键点: 确定赋值对 whiledo-while 的处理不同。

0012 以下代码输出什么?

难度: 进阶

int x;
do
{
    x = 1;
} while (flag);

Console.WriteLine(x);
  • A. 编译失败
  • B. 输出 1,do-while 至少执行一次,满足确定赋值
  • C. 输出 0
  • D. 输出取决于 flag
查看答案与解析

正确答案B

解析: do-while 的循环体必然执行一次,确定赋值分析据此判定 x 已赋值,代码编译并输出 1。

关键点:while 形成对比,这是高频陷阱。

0013 以下代码中哪些部分能通过编译?

难度: 实战

int a;
if (true) a = 1;
Console.WriteLine(a);    // 1

int b;
if (false) b = 1;
Console.WriteLine(b);    // 2
  • A. 第 1 部分和第 2 部分都能编译
  • B. 第 1 部分编译失败
  • C. 第 2 部分编译失败,if (false) 分支不可达,b 未确定赋值
  • D. 两部分都编译失败
查看答案与解析

正确答案C

解析: 确定赋值分析对常量条件做折叠:if (true) 必然进入,a 已赋值;if (false) 永不进入,b 未确定赋值报 CS0165。

关键点: 编译器会利用常量条件判定可达性。

0014 以下代码能否通过编译?

难度: 进阶

int x = 1;
{
    int x = 2;
    Console.WriteLine(x);
}
  • A. 不能,内层 x 与外层局部变量作用域冲突(CS0136)
  • B. 能,输出 2
  • C. 能,输出 1
  • D. 不能,x 未确定赋值
查看答案与解析

正确答案A

解析: 局部变量不能在外层同名局部变量仍可见的范围内再次声明,即使在外层块中,也报 CS0136;这与字段可以被局部变量遮蔽不同。

关键点: 局部变量不允许遮蔽同方法内的外层局部变量。

0015 以下代码能否通过编译?

难度: 进阶

class Sample
{
    private int _field;

    public void Run()
    {
        int local;
        _field = local;
    }
}
  • A. 能
  • B. 不能,local 未确定赋值,即使只是把它赋给字段也会报 CS0165
  • C. 不能,_field 是只读
  • D. 不能,字段不能接收局部变量的值
查看答案与解析

正确答案B

解析: 读取未确定赋值的局部变量本身就是错误,与赋值目标无关;字段默认值只适用于字段,不改变局部变量的确定赋值规则。

关键点: 局部变量必须先赋值再读取,任何读取路径都受此约束。

0016 以下代码中哪些行无法编译?

难度: 进阶

var x = 1;     // 1
var y;         // 2
var z = null;  // 3
  • A. 第 1、2 行
  • B. 第 2、3 行
  • C. 全部
  • D. 只有第 2 行
查看答案与解析

正确答案B

解析: var y; 没有初始化表达式,报 CS0818;var z = null; 无法推断类型,报 CS0815;var x = 1; 合法。

关键点: 隐式类型变量必须“有初始化且可推断”。

0017 以下 const 声明中哪一项无法编译?

难度: 实战

const string A = "a" + 1;      // 1
const int B = 1 << 10;         // 2
const double C = 1.0 / 3.0;    // 3
const int D = sizeof(int);     // 4
const object E = null;         // 5
const int F = arr.Length;      // 6
  • A. 第 1 项
  • B. 第 5 项
  • C. 第 6 项,arr.Length 不是编译期常量表达式
  • D. 全部都能编译
查看答案与解析

正确答案C

解析: 字符串常量拼接、常量位移、常量浮点除法、内置类型 sizeof、引用类型常量 null 都是合法常量表达式;数组的 Length 是运行时属性,报 CS0133。

关键点: 常量表达式的边界比多数人以为的更宽,但任何运行时求值都不行。

0018 以下代码输出什么?

难度: 进阶

var s = "x" + 1 + true;
Console.WriteLine(s);
  • A. x1True
  • B. x1
  • C. 编译失败
  • D. x1true
查看答案与解析

正确答案A

解析: 字符串加法从左到右结合:"x" + 1 得到 "x1",再 + true 调用 bool.ToString() 得到 "True"(大写 T),结果 "x1True"

关键点: boolToString() 是大写 True/False;字符串拼接会隐式调用它。

0019 以下代码输出什么?

难度: 实战

class Config
{
    public const int Base = 10;
    private static int _a = Base + 1;
    private static int _b = _a * 2;

    public int Sum => _a + _b;
}

Console.WriteLine(new Config().Sum);
  • A. 33
  • B. 32
  • C. 22
  • D. 编译失败
查看答案与解析

正确答案A

解析: _a = 10 + 1 = 11_b = 11 * 2 = 22Sum = 33const 参与静态字段初始化时按编译期值计算,不改变文本顺序语义。

关键点: 综合考察 const、静态初始化顺序与表达式求值。

0020 以下代码中哪些行能通过编译?

难度: 实战

byte b = 100;
b = b + 1;   // 1
b += 1;      // 2
  • A. 两行都能编译
  • B. 第 1 行编译失败(b + 1int,不能隐式转回 byte),第 2 行编译成功
  • C. 两行都不能编译
  • D. 第 1 行能编译,第 2 行不能
查看答案与解析

正确答案B

解析: b + 1 提升为 int,显式赋回 byte 需要转换;复合赋值运算符自带一次隐式窄化转换,b += 1 等价于 b = (byte)(b + 1),合法。

关键点: 普通赋值与复合赋值对窄化的处理不同,是经典陷阱。

官方资料

当前分类

C# 选择题

查看全部分类 →
  1. 01C# 试题 01:变量、常量与类型推断20 题
  2. 02C# 试题 02:数值类型与转换20 题
  3. 03C# 试题 03:可空类型与空值分析20 题
  4. 04C# 试题 04:运算符与表达式20 题
  5. 05C# 试题 05:流程控制20 题
ESC

输入关键词开始搜索