var是编译时类型推断,编译器在编译阶段确定具体类型并执行静态检查;dynamic是运行时动态绑定,跳过编译期类型检查,将解析推迟到程序运行时刻。使用var时若调用不存在的方法会直接报错,而使用dynamic则会在运行时抛出异常。

var的编译时行为与限制是什么?
var关键字要求必须在使用时立即初始化,因为编译器需要依据初始值来推断其确切类型。一旦推断完成,该变量就等同于被推断出的类型,后续所有操作都遵循严格的静态类型规则。如果尝试访问一个在该推断类型上不存在的成员,编译器会直接拦截并报错,不会生成可执行代码。

using System;
public class Program
{
public static void Main()
{
// 1. var 推断为 string
var name = "Hello";
Console.WriteLine(name.Length); // 正确:string 有 Length 属性
// 2. var 推断为 int
var count = 10;
// Console.WriteLine(name.ToUpper()); // 错误:int 没有 ToUpper 方法
// 3. 无法隐式转换
// var obj = null; // 错误:var 不能用于 null 初始化,因为无法推断类型
}
}
dynamic的运行时行为与优势是什么?
dynamic关键字告诉编译器放弃对该变量的静态类型检查,将其视为一个在运行时才能确定类型的对象。这使得我们可以调用任意方法或访问任意属性,即使这些成员在编译时并不存在。这种灵活性常用于处理动态语言交互、反射场景或复杂的 JSON 数据解析。如果调用的成员在运行时确实不存在,或者参数不匹配,程序会在运行那一刻抛出 RuntimeBinderException。

using System;
using System.Dynamic;
public class Program
{
public static void Main()
{
// 1. dynamic 绑定到 ExpandoObject
dynamic person = new System.Dynamic.ExpandoObject();
person.Name = "Alice";
person.Age = 30;
Console.WriteLine(person.Name); // 输出: Alice
// 2. 动态调用方法
dynamic calculator = new Calculator();
Console.WriteLine(calculator.Add(5, 3)); // 输出: 8
// 3. 错误处理:调用不存在的方法
try
{
person.NonExistentMethod();
}
catch (Microsoft.CSharp.RuntimeBinderException ex)
{
Console.WriteLine("运行时错误: " + ex.Message);
}
}
}
public class Calculator
{
public int Add(int a, int b)
{
return a + b;
}
}
当传入空值或类型不匹配时会发生什么?
对于 var,由于类型在编译期已固定,传入不兼容的类型会导致编译失败。例如,试图将一个字符串赋值给推断为整数的 var 变量是不可能的。而对于 dynamic,如果在运行时传入了错误的类型或调用了不匹配的方法,程序不会在编译时报错,而是会在执行到那一行时抛出异常。这种差异意味着 dynamic 提供了更大的灵活性,但也牺牲了编译期的安全性,开发者需要在运行时通过异常处理来保证程序的健壮性。


















