목록C#/Effective C# (50)
방프리
Item 34 : 함수를 매개변수로 사용하여 결합도를 낮추라 인터페이스를 정의하는 것보다는 델리게이트를 통해서 느슨한 결합을 만드는 것이 여러 방면에서 굉장히 좋다. /// ///인터페이스로 구현하였을 때 /// public interface IPredicate { bool Match(T soughtObject); } public class List { public void RemoveAll(IPredicate match) { //생략 } } public class MyPredicate : IPredicate { public bool Match(int target) => target < 100; } /// ///델리게이트로 구현하였을 때 /// public static IEnumerable Zip( IE..
Item 33 : 필요한 시점에 필요한 요소를 생성하라 이터레이터 메서드에 입력 매개변수로 굳이 시퀸스를 전달할 필요는 없다. 이터레이터 메서드 내에서 시퀸스를 생성하는 것도 나쁘지 않은 방법이다. 하지만 시퀸스를 생성하는 중간에 해당 시퀸스를 다른 부분에서 참조할 때 문제의 요소가 굉장히 많다. 또한 중간에 작업을 멈출 수도 없기 때문에 병목 현상이 발생할 수도 있다. 이런 시퀸스 생성 메서드를 이터레이터 함수로 구현한다면? 자연스럽게 해결될 것이다. //문제의 요소가 있는 메서드 static IList CreateSequence(int numberOfElements, int startAt, int stepBy) { var collection = new List(numberOfElements); for..
Item 32 : Action, Predicate, Function과 순회 방식을 분리하라 익명의 델리게이트를 사용할 때는 function과 action이라는 두 가지 패턴이 있다. predicate는 시퀸스 내의 항목이 조건에 부합하는지를 bool로 반환하는 function이다. predicate는 필터 메스드를 구현할 때 사용할 수 있다. public static IEnumerable Where( IEnumerable sequence, Predicate filterFunc) { if (sequence == null) throw new ArgumentNullException(nameof(sequence), "sequence must not be null"); if (filterFunc == null) ..

Item 31 : 시퀸스에 사용할 수 있는 조합 가능한 API를 작성하라 이터레이터 메서드를 사용하면 재사용성이 올라가며 추가적인 저장소를 굳이 생성할 필요가 없다. yield return을 통해 현재 위치를 계속 갱신하면서 출력 시퀸스에 차례대로 결과를 반환할 수 있다. 즉, 사용할 배열을 복사하는 것이 아닌 시퀸스 자체를 그대로 사용할 수 있다. public static IEnumerable Unique(IEnumerable nums) { var uniqueVals = new HashSet(); foreach(var num in nums) { if (!uniqueVals.Contains(num)) { uniqueVals.Add(num); yield return num; } } } yield retur..

Item 30 : 루프보다 쿼리 구문이 낫다 C# 3.0 버전부터 추가된 LinQ는 굉장히 활용범위가 넓다. 특히 예외처리나 조건처리에 관련된 코드들을 쿼리문 형태로 개발자가 사용하거나 추후 유지보수를 진행할 때 가독성을 올려주는 긍정적인 효과를 보여주었다. 반복문에서도 굉장히 가독성을 올려주는 효과가 있는데 중첩 반복문이나 조건처리에 있어서 효과가 굉장히 크다. private static IEnumerable ProduceIndices() { var storage = new List(); for (int x = 0; x < 100; x++) { for(int y = 0; y < 100; y++) { if (x + y < 100) storage.Add(Tuple.Create(x, y)); } } stor..
Item 29 : 컬렉션을 반환하기보다 이터레이터를 반환하는 것이 낫다 간단히 말해서 배열 전체를 반환하는 메서드를 생성하는 것보다 배열의 요소만을 반환하는 메서드를 구현하는 것이 최적화나 예외처리에 있어 좀 더 효율이 좋다. 실제로 컬렉션(배열)을 반환하더라도 일부분만 사용할 수도 있고, 예외처리 또한 컬렉션만 반환한다면 계속 처리해주어야 하기 때문이다. public static IEnumerable GenerateAlphabetSubset(char first, char last) { if (first 'z') throw..
Item 28 : 확장 메서드를 이용하여 구체화된 제네릭 타입을 개선하라 기존에 사용 중인 컬렉션 타입에 영향을 주지 않으면서 새로운 기능을 추가하고 싶다면 구체화된 컬렉션 타입에 대해 확장 메서드를 작성하면 된다. public static class Enumerable { public static int Average(this IEnumerable sequence); public static int Max(this IEnumerable sequence); public static int Min(this IEnumerable sequence); public static int Sum(this IEnumerable sequence); } 확장 메서드를 사용하지 않는다면 새로운 타입을 추가해야하기 때문에 되..
Item 27 : 인터페이스는 간략히 정의하고 기능의 확장은 확장 메서드를 사용하라 인터페이스에서는 최소한의 기능만 정의하고 확장 메서드를 통해 기능을 확장시키는 것이 좋다. 확장 메서드를 사용하면 기능 변경이나 추가 시에 굉장히 유용하기 때문이다. public interface IFoo { int Marker { get; set; } } public static class FooExtensions { public static void NextMarker(this IFoo thing) => thing.Marker += 1; } public class MyType : IFoo { public int Marker { get; set; } } MyType myType = new MyType(); myType...