为何未引入命名空间时var关键字仍可正常工作?
问题场景
我编写了如下代码:
var dataExistsResult = await _service.CheckifExists(RequestDto); if (dataExistsResult != null && dataExistsResult.CountProperties() > 0) //do something
但如果显式指定类型而非使用var,即写成:
PropertiesWithData dataExistsResult = await _service.CheckifExists(RequestDto);
由于当前文件未引入PropertiesWithData所在的命名空间Core.Common(该类定义如下):
namespace Core.Common { public class PropertiesWithData { // 类成员 } }
代码无法正常运行,必须添加using Core.Common;才能生效。
我有以下疑问:
- 为何使用
var时程序可正常运行? - 为何未引入命名空间,
var变量却能调用其方法(如dataExistsResult.CountProperties())? - 是否
Core.Common.PropertiesWithData是在运行时才被引入的?
解答
1. 为什么var能正常运行?
var是C#的编译时类型推断关键字,它的作用是让编译器根据等号右侧表达式的返回值,自动确定变量的具体类型。只要你的项目已经引用了包含Core.Common.PropertiesWithData的程序集,编译器在编译时就能找到这个类型的完整定义,不需要你在当前文件显式添加using Core.Common;——因为编译器自己知道这个类型的完整命名空间,只是你不用手动写出来而已。
而显式写PropertiesWithData时,编译器需要明确知道这个类型名对应的是哪个命名空间下的类,所以必须通过using指令导入命名空间,或者写完整的限定类型名(Core.Common.PropertiesWithData)才能识别。
2. 为什么var变量能调用目标类型的方法?
同样是编译时的行为:编译器已经推断出dataExistsResult的实际类型是Core.Common.PropertiesWithData,所以它能识别该类型的所有公共成员(包括CountProperties()方法)。整个类型检查、成员查找的过程都是在编译阶段完成的,和当前文件有没有导入命名空间无关——编译器已经从程序集里拿到了该类型的完整元数据。
3. 是不是运行时才引入该类型?
完全不是。所有的类型解析、成员验证都是在编译阶段完成的,运行时只负责执行编译好的IL代码。用var的时候,编译器已经把变量的类型信息写入了IL代码,和显式指定类型的最终编译结果几乎没有区别,不存在“运行时引入”的情况。
内容的提问来源于stack exchange,提问作者user3197410

