当前位置: 首页 > news >正文

【Unity开发】try-finally 与 try-catch 的区别详解

请添加图片描述

🐾 个人主页 🐾

阿松爱睡觉,横竖醒不来
🏅你可以不屠龙,但不能不磨剑🗡

文章目录

  • 一、区别对比
  • 二、try-catch 结构详解
    • 基本语法
    • 典型应用场景
  • 三、try-finally 结构详解
    • 基本语法
    • 典型应用场景
  • 四、组合使用模式
    • try-catch-finally完整结构
    • 现代简化写法(using语句)
  • 五、关键注意事项
  • 六、设计原则建议

一、区别对比

在C#和Unity开发中,异常处理是保证程序健壮性的重要机制。try-finallytry-catch虽然结构相似,但设计目的和使用场景有本质区别,我们可以对比一下二者的区别。

特性try-catchtry-finally
主要目的捕获并处理异常确保清理代码必然执行
异常处理能捕获并处理特定异常不处理异常,异常会继续向上抛出
执行保证只有发生匹配异常时catch块执行finally块始终执行(除极端情况)
适用场景业务逻辑错误处理资源释放、状态重置
代码结构必须带catch块可以不带catch块

二、try-catch 结构详解

基本语法

这种语法其实类似 if-else if-else 结构

try
{// 可能抛出异常的代码
}
catch (SpecificException ex)
{// 处理特定类型异常Debug.LogError($"特定错误: {ex.Message}");
}
catch (Exception ex)
{// 捕获所有其他异常Debug.LogError($"未知错误: {ex.StackTrace}");// 可选择重新抛出throw;
}

典型应用场景

  1. 业务逻辑错误处理

    try
    {int result = CalculateRiskScore();if(result < 0) throw new InvalidOperationException("负值无效");
    }
    catch(InvalidOperationException ex)
    {FallbackToDefaultAlgorithm();
    }
    
  2. 网络请求错误处理

    try
    {var response = await httpClient.GetAsync(url);response.EnsureSuccessStatusCode();
    }
    catch(HttpRequestException ex) when (ex.StatusCode == 404)
    {ShowNotFoundMessage();
    }
    catch(HttpRequestException ex)
    {RetryRequest();
    }
    
  3. 多异常类型处理

    try
    {ParseConfigFile();
    }
    catch(FileNotFoundException)
    {CreateDefaultConfig();
    }
    catch(JsonException)
    {RepairCorruptedConfig();
    }
    

三、try-finally 结构详解

基本语法

ResourceType resource = AcquireResource();
try
{// 使用资源的代码resource.DoWork();
}
finally
{// 无论是否异常都会执行的代码resource?.Dispose();
}

典型应用场景

  1. 资源释放保证

    FileStream file = null;
    try
    {file = File.Open("data.bin", FileMode.Open);ProcessFile(file);
    }
    finally
    {file?.Close(); // 确保文件句柄释放
    }
    
  2. 状态恢复保证

    void UpdateUI()
    {isLoading = true;try{RefreshData();}finally{isLoading = false; // 确保状态重置}
    }
    
  3. Unity对象安全操作

    GameObject tempObj = Instantiate(prefab);
    try
    {// 可能抛出NullReferenceException的操作tempObj.GetComponent<ComplexComponent>().Initialize();
    }
    finally
    {if(tempObj != null && !tempObj.GetComponent<ComplexComponent>().IsValid){Destroy(tempObj); // 确保清理无效对象}
    }
    

四、组合使用模式

try-catch-finally完整结构

StreamReader reader = null;
try
{reader = new StreamReader("config.json");var config = JsonConvert.DeserializeObject<Config>(reader.ReadToEnd());ApplyConfig(config);
}
catch(FileNotFoundException ex)
{Debug.LogWarning("配置文件缺失,使用默认配置");ApplyDefaultConfig();
}
catch(JsonException ex)
{Debug.LogError($"配置解析失败: {ex.Message}");throw new InvalidConfigException("无效配置文件", ex);
}
finally
{reader?.Dispose(); // 确保资源释放
}

现代简化写法(using语句)

// 等价于try-finally的语法糖
using(var reader = new StreamReader("config.json"))
{// 自动在离开作用域时调用Dispose()
}

五、关键注意事项

  1. finally的执行边界

    • 除进程强制终止外,finally基本都会执行
    • 以下情况finally不会执行:
      try { Environment.FailFast("紧急终止"); }
      finally { /* 不会执行 */ }
      
  2. 性能考量

    • try块本身几乎没有性能开销
    • 异常抛出和捕获(catch)的成本较高
    • 不应将异常用于正常流程控制
  3. Unity特殊场景

    IEnumerator LoadAssetCoroutine()
    {ResourceRequest request = null;try{request = Resources.LoadAsync<Texture>("large_texture");yield return request;}finally{if(request != null && request.asset == null){Resources.UnloadAsset(request.asset);}}
    }
    
  4. 异步代码中的陷阱

    async Task ProcessDataAsync()
    {// 错误示例:finally可能在异步操作完成前执行var file = File.Open("data.txt", FileMode.Open);try{await ParseAsync(file); // 异步点}finally{file.Close(); // 可能过早关闭}// 正确写法await using var properFile = File.Open("data.txt", FileMode.Open);await ParseAsync(properFile);
    }
    

六、设计原则建议

  1. 异常处理原则

    • 只捕获你能处理的异常
    • 避免空的catch块(至少记录日志)
    • 使用异常过滤器(when)细化处理
  2. 资源管理原则

    • 优先使用using替代手动try-finally
    • 确保所有IDisposable资源都被正确释放
    • Unity对象需额外检查null(因为Destroy后!=null)
  3. 代码可读性

    • 避免过深的try-catch嵌套
    • 将复杂异常处理逻辑提取到单独方法
    • 为自定义异常添加有意义的错误信息

正确使用这两种结构可以显著提高代码的健壮性。
记住核心准则:catch用于处理异常,finally用于清理资源,无论是否发生异常。

请添加图片描述
请添加图片描述

http://www.dtcms.com/a/511571.html

相关文章:

  • PHP数据库操作全攻略
  • 标准解读——GB/T 46353—2025《信息技术 大数据 数据资产价值评估》国家标准
  • Herm详解
  • 重庆网站建设哪家公司那家好winserver2008上用iis发布网站
  • HTML-CSS项目练习
  • 如何编写自动化测试用例?
  • 【Vibe Coding】001-前端界面常用布局
  • webview 中 cursor:pointer无效是由于-webkit-app-region导致的
  • 【C++】哈希表的实现【开放定址法vs链地址法】
  • 【业务逻辑漏洞】认证漏洞
  • 做网站在哪深圳做网站 汉狮网络
  • 修改k8s的镜像源为国内镜像源
  • Arbess从入门到实战(15) - 使用Arbess+GitHub实现Docker项目自动化构建部署
  • 【MySQL】从零开始了解数据库开发 ---mysql事务机制(一)
  • 网站建设明细盐都建设局网站
  • 基于单片机的气象站labview上位机监测系统
  • Chainlit+LlamaIndex 多模态 RAG 开发实战7:从系统架构到功能落地,搞定 PDF/PPT/ 图片全类型文件处理
  • 在VScode中将一个分支的某一次提交合并到另一个分支中
  • MAC M芯片安装配置VMware+Ubuntu
  • 免费seo推广软件网站排名优化软件联系方式
  • Nebula全球私有云网络部署与配置综合指南
  • LeetCode刷题总结
  • 阿里云代理商:如何开通阿里云文件存储?
  • gitee与github远程仓库
  • C语言需要掌握的基础知识点之字符串
  • 网站子页面如何做seo国家高新技术企业管理工作网
  • vs2010 iis 网站开发有没有什么需要推广的平台
  • 第六章 图——课后习题解练【数据结构(c语言版 第2版)】
  • 小米 C++ 校招二面:epoll/poll/select 区别与底层实现解析
  • 《安富莱嵌入式周报》第359期: 承包80KW水坝并自制控制系统,开源高端智能无线蓝牙耳机V2.0版发布,开源USB-C便携式台式电源