九、参数(parameter)
CLR #参数
✅ 第九章:参数
📌 1. 可选参数(Optional Parameters)
- 可以为参数指定默认值,调用时可以省略这些参数。
void Greet(string name = "Guest") {
Console.WriteLine($"Hello, {name}");
}
Greet(); // 输出 Hello, Guest
Greet("Alice"); // 输出 Hello, Alice
✅ 默认值必须是编译时常量。
📌 2. 命名参数(Named Parameters)
- 使用参数名进行调用,可以改变参数顺序:
void Info(string name, int age) { ... }
Info(age: 30, name: "Tom");
✅ 提高可读性,在调用多个可选参数的方法时非常有用。
📌 3. 隐式类型局部变量(var)
- 编译器通过赋值推断变量类型:
var x = 100; // x 是 int
var name = "Jeff"; // name 是 string
✅ 不能用于未初始化的变量。
⚠️ 不等于动态类型,var 是静态类型推断,编译时确定。
📌 4. 引用传参(ref 和 out)
✅ ref(引用传递)
- 调用方法前变量必须已赋值,方法可以修改它的值。
void Add(ref int x) { x += 10; }
✅ out(输出参数)
- 调用方法前变量不需赋值,但方法中必须赋值。
void Init(out int x) { x = 100; }
✅ out 适合返回多个结果;ref 适合传入-传出模式。
📌 5. 可变参数(params)
- 参数数量不确定时使用,必须是最后一个参数。
void Print(params int[] nums) {
foreach (int n in nums) Console.WriteLine(n);
}
Print(1, 2, 3); // 输出 1 2 3
📌 6. 参数设计规范
- 避免使用大量参数(超过 4~5 个考虑封装为对象)
- 避免使用
out/ref,改为返回Tuple或ValueTuple - 命名参数和可选参数应搭配使用以提升可维护性
- 优先使用
var让代码更简洁,但不要牺牲可读性
🚫 传统写法:使用 out 参数
//方法:从数据库查询信息,并返回状态码 & 错误信息
public bool TryGetUser(int userId, out string name, out string error) {
if (userId == 1) {
name = "Alice";
error = null;
return true;
} else {
name = null;
error = "User not found";
return false;
}
}
❌ 存在的问题:
- 返回值和逻辑混杂:
bool仅表示成功,真正有用的值通过out拆散。 - 难以测试和模拟(单元测试中无法轻易模拟多个输出值)
- IDE 支持差,特别是在调试时必须手动看每个输出参数。
✅ 推荐写法一:使用 Tuple(C# 4.0+)
public Tuple<bool, string, string> TryGetUser(int userId) {
if (userId == 1)
return Tuple.Create(true, "Alice", null);
else
return Tuple.Create(false, null, "User not found");
}
// 调用
var result = TryGetUser(1);
bool success = result.Item1;
string name = result.Item2;
string error = result.Item3;
✅ 更清晰,但 命名语义差(Item1, Item2) —— 建议使用 ValueTuple
✅ 推荐写法二:使用 ValueTuple(C# 7.0+)
public (bool success, string name, string error) TryGetUser(int userId) {
if (userId == 1)
return (true, "Alice", null);
else
return (false, null, "User not found");
}
// 调用
var (success, name, error) = TryGetUser(1);
✅ 优势:
- 命名明确,易读性强
- 返回结构可以传递、链式组合
- 易于测试与模拟(返回对象可断言)
📌 7. 常量(const)和只读字段(readonly)的区别
| 特性 | const |
readonly |
|---|---|---|
| 值设置 | 编译期确定 | 构造函数中设置 |
| 类型限制 | 仅限基础类型 | 可为任何类型 |
| 版本兼容 | 需要重新编译引用程序集 | 引用程序集不需重新编译 |
✅ 常量用于真正不变的数据(如 PI = 3.14);
✅ readonly 适合初始化后不可变但值可能随构造变化的成员(如时间戳)
🔄 Mermaid 图示:参数机制总结
graph TD
A[方法参数] --> B[可选参数]
A --> C[命名参数]
A --> D[ref/out]
A --> E[params]
A --> F[var 隐式变量]
A --> G[参数设计规范]
🧠 面试题(≥ 5 道含解析)
1️⃣ ref 和 out 有何区别?
ref:传入前必须赋值,方法中可以修改。out:传入时可以未赋值,方法中必须赋值。
2️⃣ params 有哪些限制?
- 只能有一个
params参数,且必须是最后一个参数。 - 不支持与
ref/out结合使用。
3️⃣ var 是动态类型吗?
❌ 不是。 ✅ var 是静态类型推断,在编译时由编译器推断真实类型。
4️⃣ 为什么尽量避免过多使用 ref/out?
- 会增加方法的副作用,降低可读性与测试性。
- 推荐使用元组(C# 7.0 起支持)或返回对象封装多个值。
5️⃣ const 为什么不适合跨程序集共享?
因为 const 的值在编译期就已嵌入代码中,更新常量值不会影响引用该常量的程序集。应使用 static readonly 替代。
✅ 总结
| 内容 | 要点 |
|---|---|
optional |
默认值参数,提升接口友好度 |
named |
提升调用代码可读性 |
ref/out |
传引用,ref 需初始化,out 需方法中赋值 |
params |
接收变长参数列表,编译为数组 |
var |
编译器推断静态类型,非动态类型 |
const/readonly |
const 编译期常量,readonly 构造期常量 |
点赞鼓励下,(づ ̄3 ̄)づ╭❤~
作者:世纪末的魔术师
出处:https://www.cnblogs.com/Firepad-magic/
Unity最受欢迎插件推荐:点击查看
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号