반응형

개발공부/C# 34

[Effective C#] 아이템 35 : 확장 메서드는 절대 오버로드하지 마라

확장 메서드를 사용하는 경우 대부분 기존에 개발된 타입을 개선하기 위해 사용한다. 동작 방식 변경을 위한 게 아니다. 확장 메서드를 잘못 사용한 예 확장 메서드를 이용하여 클래스를 확장하는 경우 namespace ConsoleExtensions { public static class ConsoleReport { public static string Format(this Person target) => $"{target.LastName, 20}, {target.FirstName, 15}"; } } 네임스페이스를 달리하여 확장 메서드를 추가로 정의하는 경우 namespace XmlExtensions { public static class XmlReport { public static string Format..

개발공부/C# 2021.12.10

[Effective C#] 아이템 34 : 함수를 매개변수로 사용하여 결합도를 낮추라

함수를 매개변수로 사용하는 것의 장점 개발자가 더 이상 concreate type을 작성할 필요가 없어진다. 추상화된 정의를 통해 종속성을 다룬다. 인터페이스와 클래스 분리의 특징 사용자에게 클래스 계층 구조를 강제하지 않을 수 있다. (장점) 인터페이스만 제공하기 때문에 클라이언트 코드에서 활용할 수 있는 재사용 가능 코드를 제공하기 어렵다. (단점) 인터페이스 대신 델리게이트를 사용하는 이유 델리게이트가 타입을 구성하는 핵심 구성요소가 아니기 때문이다. 델리게이트는 메서드 중 하나로 간주되지 않는다. 함수를 매개변수로 사용하는 것 장점 알고리즘 자체와 알고리즘을 적용할 타입을 분리하는데 도움이 된다. 컴포넌트를 사용하는 측과 컴포넌트를 구현하는 측의 코드를 분리할 수 있다. 단점 추가 비용이 발생한다..

개발공부/C# 2021.12.09

[Effective C#] 아이템 32 : Action, Predicate, Function과 순회 방식을 분리하라

이터레이터 메서드 유형 시퀀스 내 개별 항목을 이용하여 작업을 수행하는 유형 시퀀스의 순회 방식에 변경을 주는 유형 익명 델리게이트 패턴 function 반환 값이 있는 함수를 전달하는 델리게이트 predicate 시퀀스 내의 항목이 조건에 부합하는지를 Boolean으로 반환하는 함수. action 컬렉션 내의 개별 요소에 대해 수행할 작업을 전달하는 델리게이트. 예시 namespace System { public delegate bool Predicate(T obj); public delegate void Action(T obj); public delegate TResult Func(T arg); } 시퀀스에서 N번째 요소만 반환하는 코드 public static IEnumerable EveryNthI..

개발공부/C# 2021.12.08

[Effective C#] 아이템 31 : 시퀀스에 사용할 수 있는 조합 가능한 API를 작성해라

반복 구문이 필요한 경우 반복 구문이 필요한 경우는 대부분 여러 요소로 구성된 시퀀스를 처리하는 알고리즘을 작성하기 위한 경우이다. 이를 위해 foreach, for, while 등이 사용된다. 반복문의 효율성 반복문으로 컬렉션을 받아와서 요소를 살펴보는 경우, 효율성에 문제가 있다. 대부분 전체 컬렉션을 대상으로 여러 단계의 작업을 거친 후 원하는 결과를 얻을 수 있기 때문이다. 단계마다 전체 컬렉션을 순회해야 하기 때문에 수행 시간이 길어질 수밖에 없다. 대안 개별 요소에 대해 수행해야하는 모든 작업을 분리된 메서드로 작성한 후 루프 내에서 메서드를 호출할 수 있다. 장점 컬렉션을 한 번만 순회하면 되므로 성능이 개선된다. 중간 결과물을 저장하기 위한 컬렉션을 사용할 필요가 없기 때문에 메모리도 적게..

개발공부/C# 2021.12.07

[Effective C#] 아이템 30: 루프보다 쿼리 구문이 낫다.

쿼리 구문의 장점 프로그램의 논리를 명령형 방식에서 선언적인 방식으로 전환할 수 있다. 질의의 내용을 구성할 수 있다. 개별 항목에 대해 수행하려는 작업의 수행 시기를 연기할 수 있다. 사용자의 의도를 더 명확하게 드러낼 수 있다. 다양하게 조합할 수 있다. 루프, 쿼리, 확장 메서드 비교 루프 var foo = new int[100]; for (var num = 0; num < foo.Length; num++) { foo[num] = num * num; } foreach (int i in foo) { Console.WriteLine(i.ToString()); } 쿼리 var foo = (from n in Enumerable.Range(0, 100) select n * n).ToArray(); 개별 항목..

개발공부/C# 2021.12.06

[Effective C#] 아이템 29 : 시퀀스를 반환해야 하는 경우 컬렉션을 반환하기보다 이터레이터를 반환하는 것이 낫다.

LINQ 란? 지연된 쿼리를 지원하고 다양한 데이터 저장소에 대해 쿼리를 수행할 수 있는 통합 구문을 제공하는 기능. C# 3.0에 추가된 기능이다. 쿼리 제공자를 자유롭게 구현할 수 있다. LINQ의 목표 데이터 소스의 유형과 상관없이 동일한 작업을 수행하는 코드를 손쉽게 작성하는 것. 시퀀스를 반환해야 할 때 메서드를 작성하다보면 단일의 객체를 반환하기보다 일련의 시퀀스를 반환해야 하는 경우가 있다. 이때 컬렉션보다 이터레이터를 반환하는 것이 좋다. 이터레이터 메서드란? 호출자가 요청한 시퀀스를 생성하기 위해 yield return 문을 사용하는 메서드. 언제 이터레이터 메서드를 이용하여 시퀀스를 생성해야 하는가? 메서드가 반환하는 시퀀스를 캐싱할 때 IEnumerable와 같은 인터페이스를 반환하도..

개발공부/C# 2021.12.05

[Effective C#] 아이템 28 : 확장 메서드를 이용하여 구체화된 제네릭 타입을 개선하라

응용프로그램에서 List, Dictionary와 같이 이미 구체화된 제네릭 컬렉션을 사용하는 경우는 꽤 많다. 제네릭 컬렉션을 사용하는 이유는? 특정 타입의 집합을 다뤄야 하거나, 컬렉션이 제공하는 고유의 기능을 활용하기 위해서이다. 사용 중인 컬렉션 타입에 영향을 주지 않으면서 새로운 기능을 추가하고 싶으면 구체화된 컬렉션 타입에 대해 확장 메서드를 작성한다. 타입 매개변수로 특정 숫자 타입이 전달되었을 경우에만 사용되는 메서드들이 있다. 구체적으로 IEnumerable, IEnumerable, IEnumerable, IEnumerable 등으로 타입 매개변수가 지정된 경우에 특화된 메서드가 있다. IEnumerable에 대한 확장 메서드 확인하기 public static class Enumerable..

개발공부/C# 2021.12.04

[Effective C#] 아이템 27 : 인터페이스는 간략히 정의하고 기능의 확장은 확장 메서드를 사용하라

확장 메서드를 이용하면 인터페이스에 새로운 동작을 추가할 수 있다. 그리고 손쉽게 기능을 확장할 수 있다. 특히 API를 추가적으로 정의하지 않고도 새로운 기능을 추가할 수 있다. 확장 메서드란 미리 정의된 형식에 사용자 정의 함수를 확장(추가) 시키는 작업. 정적으로 정의해서 인스턴스 메서드처럼 사용한다. 즉, 정적 클래스에서 정의해주고 사용할 땐 확장 메서드를 정의하는 클래스가 포함된 네임스페이스를 포함(using)해줌으로 사용한다. 사용 예시 static class ExtenstionMethods{ public static void Print(this string s) { Console.WriteLine(s); } } class ExampleClass{ public static void Main(s..

개발공부/C# 2021.12.03

[Effective C#] 아이템 26 : 제네릭 인터페이스와 논제네릭 인터페이스를 함께 구현하라

새로운 라이브러리를 개발할 때 제네릭 타입뿐 아니라 고전적인 방식도 함께 지원하면 라이브러리의 활용도를 높일 수 있다. 제네릭 타입이 아닌 방식을 지원한다면, 다음 3가지에 대해 논제네릭 방식을 지원해야 한다. 클래스와 인터페이스 public 속성 serialize 대상이 되는 요소 논제네릭 방식을 지원해야 하는 이유 제네릭은 서로 다른 타입 간에 동일성을 비교하는 기능을 잘하지 못한다. 또한 단일 컬렉션 내에 다른 타입 객체를 저장해야 하는 경우에도 제네릭은 도움이 되지 않는다. 제네릭 방식에 논제네릭 방식 추가 상속 관계를 제외한 대부분의 경우 논제네릭 인터페이스를 추가하는 작업은 적절한 원형의 메서드를 추가하는 수준에서 해결된다. 논제네릭 인터페이스를 구현할 때, 개발자의 실수를 방지하기 위해 명시..

개발공부/C# 2021.12.02

[Effective C#] 아이템 25 : 타입 매개변수로 인스턴스 필드를 만들 필요가 없다면 제네릭 메서드를 정의하라

타입 매개변수로 인스턴스 필드를 만들어야 하는 경우에는 제네릭 클래스를 작성하고, 그렇지 않은 경우에는 제네릭 메서드를 작성하는 게 좋다. 제네릭으로 Min, Max 메서드를 작성해보자. 제네릭 클래스로 구현하기 public static class Utils { public static T Max(T left, T right) => Comparer.Default.Compare(left, right) Comparer.Default.Compare(left, right) < 0 ? left : right; } // 숫자 비교 방법 double d1 = 4; double d2 = 5; double max ..

개발공부/C# 2021.12.01