抛出异常后对象生命周期有多久?能否调用该对象的方法?
核心问题解答
1 异常后调用对象方法是否合法?
完全合法。你代码能正常运行也不是「GC还没销毁对象」的侥幸:GC只会回收没有任何存活强引用的对象,你的class1变量在try块外层声明,在当前方法执行结束前始终持有实例的强引用,GC无论如何都不会主动回收这个实例。
2 当前示例的可用性判断
你给出的代码逻辑是安全可用的:Calc方法的执行顺序是「先校验数据合法性→再执行计算→再写入内部存储列表」,抛出异常时,内部的calculatedPoints里存储的全是校验通过、计算完成的有效数据,状态没有被破坏,调用GetPoints获取已完成的计算结果完全符合预期。
更规范的场景适配方案
你当前的写法虽然可用,但存在隐式约定:调用方必须知道「异常抛出后还能从原对象取部分结果」,如果后续修改Calc逻辑(比如先写入列表再校验),很容易破坏状态一致性。更稳妥的实现有两种:
方案1:用返回值统一承载执行状态和结果
定义独立的结果类承载所有输出,语义明确,不需要额外约定:
// 计算结果统一返回类 public class CalcResult { public List<string> CalculatedPoints { get; } = new List<string>(); public bool IsSuccess { get; set; } public string ErrorMessage { get; set; } } // Class1的Calc方法修改为返回CalcResult public class Class1 { public CalcResult Calc(string[] values) { CalcResult result = new CalcResult(); foreach(string p in values) { if(!IsValid(p)) { result.IsSuccess = false; result.ErrorMessage = "invalid value encountered"; return result; } result.CalculatedPoints.Add(DoSomeCalculation(p)); } result.IsSuccess = true; return result; } // 省略IsValid、DoSomeCalculation等辅助方法实现 }
调用方代码:
Class1 class1 = new Class1(); CalcResult calcResult = class1.Calc(arrayOfValues); if(!calcResult.IsSuccess) { LogError(calcResult.ErrorMessage); } Draw(calcResult.CalculatedPoints);
方案2:自定义异常携带部分计算结果
如果需要保留异常抛出的错误通知逻辑,可以自定义异常类型把已计算结果一同抛出,避免原对象残留中间状态:
// 自定义计算异常类 public class CalcFailedException : Exception { public List<string> CompletedPoints { get; } public CalcFailedException(string message, List<string> completedPoints) : base(message) { CompletedPoints = completedPoints; } } // Class1实现修改 public class Class1 { private List<string> calculatedPoints = new List<string>(); public void Calc(string[] values) { List<string> tempPoints = new List<string>(); foreach(string p in values) { if(!IsValid(p)) { throw new CalcFailedException("invalid value encountered", tempPoints); } tempPoints.Add(DoSomeCalculation(p)); } // 全部计算成功才更新内部状态,避免残留中间结果 calculatedPoints = tempPoints; } public List<string> GetPoints() { return calculatedPoints; } // 省略IsValid、DoSomeCalculation等辅助方法实现 }
调用方代码:
Class1 class1 = new Class1(); List<string> pointsToDraw; try { class1.Calc(arrayOfValues); pointsToDraw = class1.GetPoints(); } catch (CalcFailedException e) { LogError(e.Message); pointsToDraw = e.CompletedPoints; } Draw(pointsToDraw);
内容的提问来源于stack exchange,提问作者isswf
相关产品推荐
相关产品推荐

