循环体中引用类型值的使用问题及优化设计模式咨询
问题根源分析
你的代码核心问题是**StdOperation是有状态的实现类**:每次调用IsMatch都会更新内部的_nameAry引用,所有匹配的Std对象的NameAry都指向同一个List实例,最终所有匹配项的结果都会被最后一次调用覆盖。
改进方案
方案1:改为无状态接口设计(推荐)
让操作直接返回处理结果,去掉接口的状态属性,从根源避免共享引用问题。
调整接口与实现
public interface IStudentOperation { // 返回null表示不匹配,否则返回拆分后的独立列表 List<string> SplitNameIfMatch(string name); } public class StdOperation : IStudentOperation { public List<string> SplitNameIfMatch(string name) { if (name.IndexOf("/") == -1) { return null; } // 每次调用都生成新列表,避免引用共享 return name.Split("/").ToList(); } }
修改Factory逻辑
public class Factory { private readonly IStudentOperation stdOpt; public Factory(IStudentOperation stdOpt) { this.stdOpt = stdOpt; } public void Do(List<Std> stdAry) { foreach (var item in stdAry) { var splitResult = this.stdOpt.SplitNameIfMatch(item.Name); if (splitResult != null) { item.NameAry = splitResult; } } } }
方案2:用值对象封装匹配结果
如果需要同时返回匹配状态和结果,可以封装成值对象,语义更清晰:
定义结果对象与接口
public class NameSplitResult { public bool IsMatch { get; } public List<string> NameAry { get; } private NameSplitResult(bool isMatch, List<string> nameAry) { IsMatch = isMatch; NameAry = nameAry; } public static NameSplitResult Match(List<string> nameAry) { return new NameSplitResult(true, nameAry); } public static NameSplitResult NoMatch() { return new NameSplitResult(false, null); } } public interface IStudentOperation { NameSplitResult ProcessName(string name); } public class StdOperation : IStudentOperation { public NameSplitResult ProcessName(string name) { if (name.IndexOf("/") == -1) { return NameSplitResult.NoMatch(); } return NameSplitResult.Match(name.Split("/").ToList()); } }
调整Factory逻辑
public void Do(List<Std> stdAry) { foreach (var item in stdAry) { var result = this.stdOpt.ProcessName(item.Name); if (result.IsMatch) { item.NameAry = result.NameAry; } } }
方案3:临时修复(不推荐)
如果无法修改原有接口,可以在赋值时创建列表副本,强行切断引用:
// 在Factory的Do方法中修改赋值逻辑 item.NameAry = new List<string>(this.stdOpt.NameAry);
这种方式只是治标不治本,有状态的服务类后续仍可能引发其他隐藏问题。
核心设计思路
服务类(如IStudentOperation的实现)应尽量设计为无状态:无状态的类更安全、易复用、易测试,从根源避免了共享可变状态带来的引用问题。
内容的提问来源于stack exchange,提问作者nil
相关产品推荐
相关产品推荐

