백엔드 개발 C#.Net 튜토리얼 .NET 예외 처리에 대한 생각(1부)

.NET 예외 처리에 대한 생각(1부)

Feb 06, 2017 pm 02:43 PM

프로젝트 개발에는 시스템과 코드의 안정성과 내결함성에 대한 해당 요구 사항이 있습니다. 실제 개발 프로젝트의 코드와 샘플 코드의 차이점은 코드 작동의 안정성, 내결함성 및 확장성에 관한 것입니다.

함수 구현에 있어서는 함수를 구현하는 핵심 코드가 동일하기 때문에 그냥 서면으로 최적화하면 되지만 특정 연산을 구현하는 데 사용되는 클래스 측면에서는 이것이 압도적으로 많다. 시간은 동일합니다.

실제 개발 과정에서는 특정 기능의 구현에만 국한되지 않고, 코드의 안정성과 확장성에 관한 문제도 많이 고려해야 할 것 같습니다.

위 내용은 실제 개발에서 직면해야 할 문제들입니다. 최근 블로그 게시물에서 저자는 이 예외를 어떻게 작성해야 할지 고민하고 있습니다. 또한 다양한 정원 친구들이 예외 작성 및 처리에 대해 자신의 의견을 제시했습니다. 여기에는 제가 이해한 내용 중 일부를 적어 보겠습니다. 상대적으로 간단하고 거칠 수 있지만 큰 사람들을 이끌기 위한 소개로만 사용됩니다. 실제 프로젝트 경험을 이야기합니다. 이 글이 모든 사람에게 도움이 되기를 바라며, 누구나 자신의 생각과 의견을 제시하고 지식과 통찰력을 공유할 수 있기를 바랍니다.

1. DotNET 예외 개요

예외에 관해서는 모든 것을 배우고 싶다면 무엇을 배우고 싶은지 알아야 합니다. 마음 속으로 대략적인 이해를 갖는 것이 좋습니다. 구성원이 이름에 명시된 작업을 수행하지 못하는 경우 예외가 발생합니다.

.NET에서 생성자, 속성 가져오기 및 설정, 이벤트 추가 및 삭제, 연산자 오버로드 호출, 변환 연산자 호출 등은 오류 코드를 반환할 방법이 없지만 이러한 구문에서 오류를 보고해야 합니다. , 예외 처리 메커니즘을 제공해야 합니다.

예외 처리에서 우리가 자주 사용하는 세 가지 블록은 try block; finally block입니다. 이 세 블록은 함께 사용할 수도 있고 catch 블록 없이 사용할 수도 있습니다. 구체적인 방법은 아래에 설명되어 있습니다.

예외 처리 메커니즘에는 일반적으로 세 가지 옵션이 있습니다. 동일한 예외를 다시 발생시키고 호출 스택에서 한 수준 더 높은 코드에 예외 발생을 알리는 것입니다. 호출 스택 한 계층의 코드는 더 풍부한 예외 정보를 제공하여 스레드가 catch 블록의 맨 아래에서 종료되도록 합니다.

예외 처리 방법에 대한 몇 가지 지침 제안이 있습니다.

1. finally 블록의 올바른 사용

finally 블록은 스레드가 어떤 유형의 예외를 발생시키더라도 일반적으로 작업을 정리하는 데 사용됩니다. 그런 다음 호출자나 finally 블록 뒤의 코드로 돌아갑니다.

2. 예외 캡처가 적절해야 합니다

예외 캡처가 적절해야 하는 이유는 무엇인가요? 다음 코드는 모든 예외를 포착할 수 없기 때문에 예외를 포착한 후에는 이러한 예외를 처리해야 합니다. 모든 예외를 포착했지만 발생할 예외를 예측하지 못하면 이러한 예외를 처리할 방법이 없습니다.

애플리케이션 코드에서 예외가 발생하면 애플리케이션의 반대쪽 끝에서 이 예외를 포착할 것으로 예상할 수 있으므로 "모든 크기에 맞는" 예외 블록으로 작성할 수 없으며 예외가 다음과 같이 허용되어야 합니다. 호출 스택을 위로 이동하고 애플리케이션 코드가 이 예외를 구체적으로 처리하도록 합니다.

catch 블록에서는 System.Exception을 사용하여 예외를 catch할 수 있지만 catch 블록 끝에서 예외를 다시 발생시키는 것이 더 좋습니다. 이유는 나중에 설명하겠습니다.

try{
  var hkml = GetRegistryKey(rootKey);
  var subkey = hkml.CreateSubKey(subKey);
  if (subkey != null && keyName != string.Empty)
  subkey.SetValue(keyName, keyValue, RegistryValueKind.String);
}
catch (Exception ex)
{
         Log4Helper.Error("创建注册表错误" + ex);
         throw new Exception(ex.Message,ex);
}
로그인 후 복사

3. 예외 복구

예외를 포착한 후 프로그램이 계속 실행되도록 특별히 몇 가지 예외 복구 코드를 작성할 수 있습니다. 예외를 포착할 때는 특정 예외를 포착하고, 어떤 상황에서 예외가 발생하는지 완전히 이해하고, 포착된 예외 유형에서 어떤 유형이 파생되는지 알아야 합니다. catch 블록 끝에서 다시 발생하지 않는 한 System.Exception 예외를 처리하거나 catch하지 마세요.

4. 상태 유지

일반적으로 작업이나 메서드를 완료하면 이를 완료하기 위해 여러 메서드의 조합을 호출해야 합니다. 후자의 방법에서 예외가 발생했습니다. 복구할 수 없는 예외가 발생하면 부분적으로 완료된 작업이 롤백됩니다. 정보를 복원해야 하기 때문입니다. 따라서 예외를 포착할 때 모든 예외 정보를 캡처해야 합니다.

5. 계약을 유지하기 위해 구현 세부 정보를 숨깁니다.

경우에 따라 예외를 포착하고 다른 예외를 다시 발생시켜야 할 수도 있습니다. 이렇게 하면 메서드의 계약이 유지될 수 있으며 발생된 예외 유형은 다음과 같습니다. be는 특별한 예외입니다. 다음 코드를 보세요:

FileStream fs = null;
            try
            {
                fs = FileStream();
              
            }
            catch (FileNotFoundException e)
            {
          //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常
                throw new NameNotFoundException();
            }
            catch (IOException e)
            {
 
               //抛出一个不同的异常,将异常信息包含在其中,并将原来的异常设置为内部异常
             throw new NameNotFoundException(); 
            } 
            finally 
            {
               if (fs != null) 
                { 
               fs.close(); 
            } 
            }
로그인 후 복사

위 코드는 단지 처리 방법을 보여줍니다. 발생하는 모든 예외는 해당 예외를 "삼키고" 새 예외를 발생시키는 대신 메서드의 호출 스택으로 전달되어야 합니다. 형식 생성자가 예외를 throw하고 해당 예외가 형식 생성자 메서드에서 포착되지 않는 경우 CLR은 내부적으로 예외를 포착하고 대신 새 TypeInitialztionException을 발생시킵니다.

2. DotNET 예외에 대한 일반적인 처리 메커니즘

在代码发生异常后,我们需要去处理这个异常,如果一个异常没有得到及时的处理,CLR会终止进程。在异常的处理中,我们可以在一个线程捕获异常,在另一个线程中重新抛出异常。异常抛出时,CLR会在调用栈中向上查找与抛出的异常类型匹配的catch块。如果没有任何catch块匹配抛出的异常类型,就发生一个未处理异常。CLR检测到进程中的任何线程有一个位处理异常,都会终止进程。

1.异常处理块

(1).try块:包含代码通常需要执行一些通用的资源清理操作,或者需要从异常中恢复,或者两者都需要。try块还可以包含也许会抛出异常的代码。一个try块至少有一个关联的catch块或finall块。

(2).catch块:包含的是响应一个异常需要执行的代码。catch关键字后的圆括号中的表达式是捕获类型。捕获类型从System.Exception或者其派生类指定。CLR自上而下搜素一个匹配的catch块,所以应该教具体的异常放在顶部。一旦CLR找到一个具有匹配捕获类型的catch块,就会执行内层所有finally块中的代码,”内层finally“是指抛出异常的tey块开始,到匹配异常的catch块之间的所有finally块。

使用System.Exception捕捉异常后,可以采用在catch块的末尾重新抛出异常,因为如果我们在捕获Exception异常后,没有及时的处理或者终止程序,这一异常可能对程序造成很大的安全隐患,Exception类是所有异常的基类,可以捕获程序中所有的异常,如果出现较大的异常,我们没有及时的处理,造成的问题是巨大的。

(3).finally块:包含的代码是保证会执行的代码。finally块的所有代码执行完毕后,线程退出finally块,执行紧跟在finally块之后的语句。如果不存在finally块,线程将从最后一个catch块之后的语句开始执行。

备注:异常块可以组合和嵌套,对于三个异常块的样例,在这里就不做介绍,异常的嵌套可以防止在处理异常的时候再次出现未处理的异常,以上这些就不再赘述。

2.异常处理实例


(1).异常处理扩展方法

 /// <summary>
        ///  格式化异常消息
        /// </summary>
        /// <param name="e">异常对象</param>
        /// <param name="isHideStackTrace">是否隐藏异常规模信息</param>
        /// <returns>格式化后的异常信息字符串</returns>
        public static string FormatMessage(this Exception e, bool isHideStackTrace = false)
        {
            var sb = new StringBuilder();
            var count = 0;
            var appString = string.Empty;
            while (e != null)
            {
                if (count > 0)
                {
                    appString += "  ";
                }
                sb.AppendLine(string.Format("{0}异常消息:{1}", appString, e.Message));
                sb.AppendLine(string.Format("{0}异常类型:{1}", appString, e.GetType().FullName));
                sb.AppendLine(string.Format("{0}异常方法:{1}", appString, (e.TargetSite == null ? null : e.TargetSite.Name)));
                sb.AppendLine(string.Format("{0}异常源:{1}", appString, e.Source));
                if (!isHideStackTrace && e.StackTrace != null)
                {
                    sb.AppendLine(string.Format("{0}异常堆栈:{1}", appString, e.StackTrace));
                }
                if (e.InnerException != null)
                {
                    sb.AppendLine(string.Format("{0}内部异常:", appString));
                    count++;
                }
                e = e.InnerException;
            }
            return sb.ToString();
        }
로그인 후 복사

(2).验证异常

 /// <summary>
        /// 检查字符串是空的或空的,并抛出一个异常
        /// </summary>
        /// <param name="val">值测试</param>
        /// <param name="paramName">参数检查名称</param>
        public static void CheckNullOrEmpty(string val, string paramName)
        {
            if (string.IsNullOrEmpty(val))
                throw new ArgumentNullException(paramName, "Value can&#39;t be null or empty");
        }

        /// <summary>
        /// 请检查参数不是空的或空的,并抛出异常
        /// </summary>
        /// <param name="param">检查值</param>
        /// <param name="paramName">参数名称</param>
        public static void CheckNullParam(string param, string paramName)
        {
            if (string.IsNullOrEmpty(param))
                throw new ArgumentNullException(paramName, paramName + " can&#39;t be neither null nor empty");
        }

        /// <summary>
        /// 检查参数不是无效,并抛出一个异常
        /// </summary>
        /// <param name="param">检查值</param>
        /// <param name="paramName">参数名称</param>
        public static void CheckNullParam(object param, string paramName)
        {
            if (param == null)
                throw new ArgumentNullException(paramName, paramName + " can&#39;t be null");
        }
        /// <summary>
        /// 请检查参数1不同于参数2
        /// </summary>
        /// <param name="param1">值1测试</param>
        /// <param name="param1Name">name of value 1</param>
        /// <param name="param2">value 2 to test</param>
        /// <param name="param2Name">name of vlaue 2</param>
        public static void CheckDifferentsParams(object param1, string param1Name, object param2, string param2Name)
        {
            if (param1 == param2) {
                throw new ArgumentException(param1Name + " can&#39;t be the same as " + param2Name,
                    param1Name + " and " + param2Name);
            }
        }

        /// <summary>
        /// 检查一个整数值是正的(0或更大)
        /// </summary>
        /// <param name="val">整数测试</param>
        public static void PositiveValue(int val)
        {
            if (val < 0)
                throw new ArgumentException("The value must be greater than or equal to 0.");
        }
로그인 후 복사

(3).Try-Catch扩展操作

 /// <summary>
        ///     对某对象执行指定功能与后续功能,并处理异常情况
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="source">值</param>
        /// <param name="action">要对值执行的主功能代码</param>
        /// <param name="failureAction">catch中的功能代码</param>
        /// <param name="successAction">主功能代码成功后执行的功能代码</param>
        /// <returns>主功能代码是否顺利执行</returns>
        public static bool TryCatch<T>(this T source, Action<T> action, Action<Exception> failureAction,
            Action<T> successAction) where T : class
        {
            bool result;
            try
            {
                action(source);
                successAction(source);
                result = true;
            }
            catch (Exception obj)
            {
                failureAction(obj);
                result = false;
            }
            return result;
        }
        /// <summary>
        ///     对某对象执行指定功能,并处理异常情况
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="source">值</param>
        /// <param name="action">要对值执行的主功能代码</param>
        /// <param name="failureAction">catch中的功能代码</param>
        /// <returns>主功能代码是否顺利执行</returns>
        public static bool TryCatch<T>(this T source, Action<T> action, Action<Exception> failureAction) where T : class
        {
            return source.TryCatch(action,
                failureAction,
                obj => { });
        }
        /// <summary>
        ///     对某对象执行指定功能,并处理异常情况与返回值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="TResult">返回值类型</typeparam>
        /// <param name="source">值</param>
        /// <param name="func">要对值执行的主功能代码</param>
        /// <param name="failureAction">catch中的功能代码</param>
        /// <param name="successAction">主功能代码成功后执行的功能代码</param>
        /// <returns>功能代码的返回值,如果出现异常,则返回对象类型的默认值</returns>
        public static TResult TryCatch<T, TResult>(this T source, Func<T, TResult> func, Action<Exception> failureAction,
            Action<T> successAction)
            where T : class
        {
            TResult result;
            try
            {
                var u = func(source);
                successAction(source);
                result = u;
            }
            catch (Exception obj)
            {
                failureAction(obj);
                result = default(TResult);
            }
            return result;
        }
        /// <summary>
        ///     对某对象执行指定功能,并处理异常情况与返回值
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="TResult">返回值类型</typeparam>
        /// <param name="source">值</param>
        /// <param name="func">要对值执行的主功能代码</param>
        /// <param name="failureAction">catch中的功能代码</param>
        /// <returns>功能代码的返回值,如果出现异常,则返回对象类型的默认值</returns>
        public static TResult TryCatch<T, TResult>(this T source, Func<T, TResult> func, Action<Exception> failureAction)
            where T : class
        {
            return source.TryCatch(func,
                failureAction,
                obj => { });
        }
로그인 후 복사

本文没有具体介绍try,catch,finally的使用,而是给出一些比较通用的方法,主要是一般的开发者对于三个块的使用都有一个认识,就不再做重复的介绍。

以上就是关于.NET异常处理的思考(上)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C++ 함수 예외 및 멀티스레딩: 동시 환경의 오류 처리 C++ 함수 예외 및 멀티스레딩: 동시 환경의 오류 처리 May 04, 2024 pm 04:42 PM

C++의 함수 예외 처리는 다중 스레드 환경에서 스레드 안전성과 데이터 무결성을 보장하는 데 특히 중요합니다. try-catch 문을 사용하면 특정 유형의 예외가 발생할 때 이를 포착하고 처리하여 프로그램 충돌이나 데이터 손상을 방지할 수 있습니다.

여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 여러 .NET 오픈 소스 AI 및 LLM 관련 프로젝트 프레임워크 공유 May 06, 2024 pm 04:43 PM

오늘날 인공지능(AI) 기술 개발은 본격화되고 있으며, 다양한 분야에서 큰 잠재력과 영향력을 보여주고 있습니다. 오늘 Dayao는 여러분에게 몇 가지 참고 자료를 제공하고자 4개의 .NET 오픈 소스 AI 모델 LLM 관련 프로젝트 프레임워크를 공유할 것입니다. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel은 OpenAI, Azure와 같은 대규모 언어 모델(LLM)을 통합하도록 설계된 오픈 소스 소프트웨어 개발 키트(SDK)입니다.

Java 함수의 재귀 호출과 예외 처리 간의 관계는 무엇입니까? Java 함수의 재귀 호출과 예외 처리 간의 관계는 무엇입니까? May 03, 2024 pm 06:12 PM

재귀 호출의 예외 처리: 재귀 깊이 제한: 스택 오버플로 방지. 예외 처리 사용: try-catch 문을 사용하여 예외를 처리합니다. 꼬리 재귀 최적화: 스택 오버플로를 방지합니다.

C++ 예외 처리는 사용자 정의 오류 처리 루틴을 어떻게 지원합니까? C++ 예외 처리는 사용자 정의 오류 처리 루틴을 어떻게 지원합니까? Jun 05, 2024 pm 12:13 PM

C++ 예외 처리를 사용하면 예외를 발생시키고 try-catch 블록을 사용하여 이를 잡아 런타임 오류를 처리하는 사용자 정의 오류 처리 루틴을 만들 수 있습니다. 1. 예외 클래스에서 파생된 사용자 정의 예외 클래스를 생성하고 what() 메서드를 재정의합니다. 2. 예외를 발생시키려면 throw 키워드를 사용합니다. 3. 예외를 포착하고 가능한 예외 유형을 지정합니다. 처리.

C++ Lambda 표현식에서 예외를 처리하는 방법은 무엇입니까? C++ Lambda 표현식에서 예외를 처리하는 방법은 무엇입니까? Jun 03, 2024 pm 03:01 PM

C++ Lambda 표현식의 예외 처리에는 자체 범위가 없으며 기본적으로 예외가 포착되지 않습니다. 예외를 포착하려면 Lambda 표현식 포착 구문을 사용하면 됩니다. 이 구문을 사용하면 Lambda 표현식이 정의 범위 내에서 변수를 캡처하여 try-catch 블록에서 예외를 처리할 수 있습니다.

C++ 기술의 예외 처리: 다중 스레드 환경에서 예외를 올바르게 처리하는 방법은 무엇입니까? C++ 기술의 예외 처리: 다중 스레드 환경에서 예외를 올바르게 처리하는 방법은 무엇입니까? May 09, 2024 pm 12:36 PM

다중 스레드 C++에서 예외 처리는 적시성, 스레드 안전성 및 명확성이라는 원칙을 따릅니다. 실제로는 뮤텍스 또는 원자 변수를 사용하여 예외 처리 코드의 스레드 안전성을 보장할 수 있습니다. 또한 다중 스레드 환경에서 안전하고 효율적으로 실행되도록 예외 처리 코드의 재진입, 성능 및 테스트를 고려하십시오.

PHP 예외 처리: 예외 추적을 통해 시스템 동작 이해 PHP 예외 처리: 예외 추적을 통해 시스템 동작 이해 Jun 05, 2024 pm 07:57 PM

PHP 예외 처리: 예외 추적을 통해 시스템 동작 이해 예외는 PHP에서 오류를 처리하는 데 사용하는 메커니즘이며 예외는 예외 처리기에 의해 처리됩니다. 예외 클래스 Exception은 일반적인 예외를 나타내고, Throwable 클래스는 모든 예외를 나타냅니다. throw 키워드를 사용하여 예외를 발생시키고 try...catch 문을 사용하여 예외 처리기를 정의합니다. 실제 사례에서는 예외 처리를 사용하여 오류가 발생할 때 응용 프로그램이 정상적으로 실패할 수 있도록 계산() 함수에서 발생할 수 있는 DivisionByZeroError를 캡처하고 처리합니다.

PHP에서 예외를 효과적으로 처리하는 방법 (시도, 잡기, 마지막으로, 던지기)? PHP에서 예외를 효과적으로 처리하는 방법 (시도, 잡기, 마지막으로, 던지기)? Apr 05, 2025 am 12:03 AM

PHP에서는 시도, 캐치, 마지막으로 키워드를 통해 예외 처리가 이루어집니다. 1) 시도 블록은 예외를 던질 수있는 코드를 둘러싸고 있습니다. 2) 캐치 블록은 예외를 처리합니다. 3) 마지막으로 블록은 코드가 항상 실행되도록합니다. 4) 던지기는 수동으로 예외를 제외하는 데 사용됩니다. 이러한 메커니즘은 코드의 견고성과 유지 관리를 향상시키는 데 도움이됩니다.

See all articles