C#如何在方法签名中标记已修改和未修改的类类型入参
关于in/ref/out修饰符的使用效果
- 标记参数b永不修改:可以使用
in修饰符达成部分需求。in会将参数限制为只读引用,你无法在函数内部为b重新赋值新的B实例,也无法修改b的引用指向,可明确表达「参数本身的引用不会被修改」的语义。但要注意:in无法阻止你修改b的内部字段或属性,如果你的「永不修改」要求连内部成员都不能改动,仅靠in修饰符无法完全满足。 - 标记参数a会被修改:
ref/out修饰符都不适配你当前的场景。这两个修饰符的作用是允许你修改参数本身的引用指向(比如在函数内执行a = new A(),会同步修改外部传入的变量的引用),而你当前的代码只是修改a的内部字段,不需要ref/out就可以生效,且这两个修饰符也无法表达「仅修改参数内部成员」的语义,达不到你要的标记效果。
可实现标记需求的C#特性
你可以使用System.Diagnostics.CodeAnalysis命名空间下的特性实现更精准的语义标记,同时还能触发静态代码检查:
- 给参数b加上
[ReadOnly]特性:明确告知调用方和静态分析工具,该参数的实例本身、以及其所有成员都不会在方法内被修改,一旦代码中出现修改b成员的逻辑,静态分析工具会抛出警告。 - 给参数a加上
[Out]特性:该特性原本用于COM互操作场景,现在已被.NET静态分析工具识别为「方法会修改该参数的内部状态」的语义标记,正好匹配你的需求。
修改后的函数签名参考:
void func([Out] A a, [ReadOnly] in B b) { a.field = b.field; }
内容的提问来源于stack exchange,提问作者lezebulon
相关产品推荐
相关产品推荐

