목록C#/Effective C# (50)
방프리
Item 50 : 예외 필터의 다른 활용 예를 살펴보라 예외필터를 통해 다양한 방법으로 여러 가지 기능을 제공할 수 있다. 첫 번째로 항상 false만을 반환하여 제한된 타입에 대해서만 로그를 출력할 수 있다. try { data = MakeWebRequest(); } catch (Exception e) when (ConsoleLogException(e)) { } catch (TimeoutException e) when (failures++ < 10) { WriteLine("Timeout error: trying again"); } public static bool ConsoleLogException(Exception e) { var oldColor = Console.ForegroundColor; Con..
Item 49 : catch 후 예외를 다시 발생시키는 것보다 예외 필터가 낫다. 예외가 발생한 이후 catch 구문에서 어떠한 조건을 넣으려고 할 때 되도록 if 구문보다 아예 catch에서 when 키워드를 통해 조건을 거는 것이 좋다. var retryCount = 0; var dataString = default(String); while (dataString == null) { try { dataString = MakeWebRequest(); } catch (TimeoutException e) when (retryCount++ < 3) { WriteLine("Operation timed out. Trying again"); Task.Delay(1000 * retryCount); } } 만약 ca..
Item 48: 강력한 예외 보증을 준수하는 것이 좋다. 해당 항목에서 총 3가지의 예외 보증을 소개한다. 각각 기본 보증, 강력한 보증, 예외 없음 보증이다. 첫 번째로 기본 보증은 특정 함수 내에서 발생한 예외가 이 함수를 빠져나오더라도 어떤 리소스도 누수되지 않으며, 모든 객체의 상태가 유요한 상태를 유지하는 것을 뜻한다. NET CLR은 이 기본 보증을 준수하며 모든 기본 보증은 강력한 보증을 준수함으로써 해결이 가능하다. 두 번째로 강력한 보증이란 정의를 내리자면 다음과 같다. 방어적인 프로그램을 위해 수정할 데이터에 대한 복사본을 마련한다. 복사해둔 데이터를 수정한다. 수정 과정에서 예외가 발생할 수 있다. 수정된 복사본과 원본 데이터를 교환한다. 이 교환 작업은 예외를 일으켜서는 안 된다. ..
Item 47 : 사용자 지정 예외 클래스를 완벽하게 작성하라 예외처리는 프로그래머라면 반드시 해주어야 하는 필수항목이다. 예외를 처리할 때 Exception 클래스를 통해 통합적인 예외처리를 하는 방법과 NullReferenceException 같은 특수 Exception 클래스를 인자로 예외처리 하는 두 가지 방식으로 나뉜다. 이 항목에서 저자는 전자가 아닌 후자로 처리하되 자신이 만든 클래스 타입에서 예외 처리를 해야한다면 반드시 그 클래스에 맞는 예외 클래스도 만들어주어야 한다고 강조한다. //모든 예외를 처리할 수 있지만 정확한 원인 파악이 어려움 try { DoWork(); } catch (Exception e) { CatchException(); } finally { LastWork(); }..
Item 46 : 리소스 정리를 위해 using과 try/finally를 활용하라 C에는 malloc과 free, C++에 new, delete가 있다면 C#에는 new, Dispose()가 있다. C#에서는 가비지 컬렉터에서 어느 정도 리소스를 자동으로 해제해주기 때문에 큰 리소스를 관리하지 않는 이상 Dispose()를 사용할 일이 크게 없다. 만약 사용하게 된다면 반드시 IDisposable 인터페이스를 구현해주어야 한다. 하지만 많은 사람들은 직접 Dispose() 하는 것을 그렇게 추천하지 않는다. 아무래도 자동으로 메모리를 해제하는 동작에 최대한 간섭을 주지 않게 하기 위해서인 것 같다. 만약 사용하게 된다면 일일히 delete처럼 Dispose()를 사용해주어야 하는데, 이를 좀 더 간편하게..
Item 45 : 메서드가 실패했음을 알리기 위해서 예외를 사용하라 개발자라면 예외처리는 항상 유념해두어야 하는 항목 중 하나이다. 그리고 예외처리라고 하면 가장 먼저 떠오르는 것은 바로 try/catch 일 것이다. 하지만 해당 주제에서 저자는 try/catch 뿐만이 아닌 메서드의 분할을 통해서 좀 더 세밀하게 예외 처리하는 방식을 추천하고 있다. public class DoesWorkThatMightFail { public bool TryDoWork() { if (!TestConditions()) return false; Work(); return true; } public void DoWork() { Work(); } private bool TestConditions() { return true;..
Item 44 : 바인딩된 변수는 수정하지 말라 이번에도 클로저를 사용했을 때의 경우 유의해야하는 부분이다. 쿼리문을 실행하면서 지역 변수라든지 이미 클로저에서 캡쳐된 변수를 수정하는 코드를 넣을 수도 있는데 이는 컴파일러가 어떻게 동작을 할 것인지 결정에 따라 동작 방식이 크게 차이가 난다. public class ModFilter { private readonly int modulus; public ModFilter(int mod) { modulus = mod; } public IEnumerable FindValues(IEnumerable sequence) { int numValues = 0; return from n in sequence where n % modulus == 0 select n * ..
Item 43 : 쿼리 결과의 의미를 명확히 강제하고, Single()과 First()를 사용하라 쿼리를 통해서 데이터를 가져오는 방법은 여러가지가 있다. ToList(), ToArray() 등을 통해 시퀸스 형식을 가져오는 방법과 Single(), First() 등을 통해 단일 요소를 가져오는 방법으로 나뉜다. 이 중 단일 요소를 가져올 때 Single()과 First()의 차이를 유의해야한다. 간단하게 쿼리문을 통해 얻고자 하는 데이터가 무조건 하나일 경우 Single(), 여러 개가 있을 경우에는 First()를 사용하면 된다. //Index가 기본키라고 할 때 기본키는 해당 테이블에서 하나만 존재할 수 있으므로 var singleElement = dbContext.MyTable.Where(p =>..