목록C# (122)
방프리

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...
Item 26 : 제네릭 인터페이스와 논제네릭 인터페이스를 함께 구현하라 제네릭 타입은 C# 초기부터 있던 기능이 아니기 때문에 예전버전까지 호환해야한다면 이를 고려해야 한다. 세 가지 요소(클래스와 인터페이스, public 속성, Serialize)를 모두 지원해주어야 한다. 하단의 코드는 논제네릭 방식으로 구현된 (레거시 코드) Name 클래스이다. public class Name : IComparable, IEquatable { public string First { get; set; } public string Last { get; set; } public string Middle { get; set; } public int CompareTo(Name other) { if (Object.Refer..
Item 25 : 타입 매개변수로 인스턴스 필드를 만들 필요가 없다면 제네릭 메서드를 정의하라 저자는 제네릭을 사용할수록 개발자가 점점 실수를 할 수 있는 부분에 대해 염려한 것 같다. 이번 주제는 한마디로 줄이자면 편함을 버리자는 것이다. 아무 생각 없이 제네릭 클래스를 만드는 습관의 위험성인데 제네릭 클래스를 관리하다보면 제약조건이 점점 늘어날 수 있는데 그럴 경우마다 수정의 범위가 넓어진다. public static class Utils { public static T Max(T left, T right) => Comparer.Default.Compare(left, right) < 0 ? right : left; public static double Max(double left, double rig..
Item 24 : 베이스 클래스나 인터페이스에 대해서 제네릭을 특화하지 말라 제네릭 클래스나 제네릭 메서드를 작성할 때는 사용자가 가능한 한 안전하고 혼란스럽지 않게 작성해야야한다. 특히 오버로드된 메서드가 여러 개인 경우, 컴파일러가 어떤 메서드를 선택하는지 정확히 알아야한다. 다음 예제를 통해서 어떤 메서드를 우선으로 호출하는지 확인해볼 수 있다. using static System.Console; public class MyBase { } public interface IMessageWriter { void WriteMessage(); } public class MyDerived : MyBase, IMessageWriter { void IMessageWriter.WriteMessage() => Wr..