Section 49.3: 명명된 인자 (Named Argument) 를 사용하여 코드를 보다 명확하게 작성하기

다음과 같은 간단한 클래스가 있는 경우를 생각해 본다:

class SmsUtil { public bool SendMessage(string from, string to, string message, int retryCount, object attachment) { // 추가적인 코드 부분 } }

C# 3.0 이전 버전에서의 위 메소드 호출 코드는 다음과 같다:

var result = SmsUtil.SendMessage("Mehran", "Maryam", "Hello there!", 12, null);

명명된 인자 (Named Argument) 를 사용하면, 아래와 같이 보다 명확한 코드를 통해 메소드를 호출할 수 있다:

var result = SmsUtil.SendMessage( from: "Mehran", to: "Maryam", message "Hello there!", retryCount: 12, attachment: null);
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 49.2: 명명된 인자 (Named Argument) 와 선택적 인자 (Optional Parameter)

명명된 인자 (Named Argument) 와 선택적 인자 (Optional Parameter) 는 함께 사용이 가능하다.

다음과 같은 메소드를 확인한다:

public sealed class SmsUtil { public static bool SendMessage(string from, string to, string message, int retryCount = 5, object attachment = null) { // 추가적인 코드 부분 } }

위 메소드에서, 끝에서 두번째에 위치한 retryCount 파라미터만 제외한채로 메소드 호출을 하고 싶다면, 다음과 같이 코드를 작성할 수 있다:

var result = SmsUtil.SendMessage( from: "Cihan", to: "Yakar", message: "Hello there!", attachment: new object());
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 49.1: 순서가 필요없는 명명된 인자 (Named Argument) 사용하기

명명된 인자 (Named Argument) 를 사용하면, 인자의 순서를 사용자가 원하는 어떠한 순서대로 기술하여도 정상 동작에 문제가 없다.

Sample 메소드:

public static string Sample(string left, string right) { return string.Join("-",left,right); }

Sample 메소드 호출:

Console.WriteLine (Sample(left:"A",right:"B")); Console.WriteLine (Sample(right:"A",left:"B"));

결과:

A-B B-A
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 48.17: 예외적인 특수한 처리를 위해 확장 메소드 이용하기

확장 메소드는 호출하는 함수를 if/then 조합으로 뒤덮일 수도 있는 복잡한 비즈니스 로직을 숨기기 위해 사용될 수 있다. 이는 확장 메소드를 이용해 null 값을 처리하는 방식과 유사하다. 다음 예제를 확인한다:

public static class CakeExtensions { public static Cake EnsureTrueCake(this Cake cake) { // 만약 이 케익이 가짜라면, 조금 맛이 떨어지긴 하지만 절대 가짜일리는 없는 할머니의 케익으로 대체한다. 만약 이 케익이 가짜가 아니라면, 아무 일도 하지 않고 바로 해당 케익을 반환한다. return CakeVerificationService.IsCakeLie(cake) ? GrandmasKitchen.Get1950sCake() : cake; } } Cake myCake = Bakery.GetNextCake().EnsureTrueCake(); myMouth.Eat(myCake); // 가짜일 수 있다는 걱정 없이 케익을 바로 먹을 수 있다.
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 48.16: 확장 메소드를 사용하여 새로운 collection 타입 (예:DictList) 생성하기

List<T> 를 값으로 갖는 Dictionary 와 같은, 새로운 중첩 collection 타입을 확장메소드를 통해 보다 편리하게 사용할 수 있도록 만들 수 있다.

다음과 같은 확장 메소드가 있다고 가정하면:

public static class DictListExtensions { public static void Add < TKey, TValue, TCollection > (this Dictionary < TKey, TCollection > dict, TKey key, TValue value) where TCollection: ICollection < TValue > , new() { TCollection list; if (!dict.TryGetValue(key, out list)) { list = new TCollection(); dict.Add(key, list); } list.Add(value); } public static bool Remove < TKey, TValue, TCollection > (this Dictionary < TKey, TCollection > dict, TKey key, TValue value) where TCollection: ICollection < TValue > { TCollection list; if (!dict.TryGetValue(key, out list)) { return false; } var ret = list.Remove(value); if (list.Count == 0) { dict.Remove(key); } return ret; } }

위 확장 메소드를 다음과 같이 사용할 수 있다:

var dictList = new Dictionary<string, List<int>>(); dictList.Add("example", 5); dictList.Add("example", 10); dictList.Add("example", 15); Console.WriteLine(String.Join(", ", dictList["example"])); // 5, 10, 15 dictList.Remove("example", 5); dictList.Remove("example", 10); Console.WriteLine(String.Join(", ", dictList["example"])); // 15 dictList.Remove("example", 15); Console.WriteLine(dictList.ContainsKey("example")); // False

데모 확인하기

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 48.15: 확장 메소드를 사용하여 편리한 mapper 클래스 만들기

확장 (extension) 메소드를 이용하면, 보다 편리한 mapper 클래스를 만들 수 있다. 다음과 같은 DTO 클래스들이 존재하는 경우를 생각해보자.

public class UserDTO { public AddressDTO Address { get; set; } } public class AddressDTO { public string Name { get; set; } }

이제 각 클래스들을 아래와 같이 대응되는 view model 클래스들로 매핑시켜야 한다.

public class UserViewModel { public AddressViewModel Address { get; set; } } public class AddressViewModel { public string Name { get; set; } }

이러한 경우, 아래와 같은 mapper 클래스를 정의할 수 있다.

public static class ViewModelMapper { public static UserViewModel ToViewModel(this UserDTO user) { return user == null ? null : new UserViewModel() { Address = user.Address.ToViewModel() // Job = user.Job.ToViewModel(), // Contact = user.Contact.ToViewModel() .. 기타 등등 }; } public static AddressViewModel ToViewModel(this AddressDTO userAddr) { return userAddr == null ? null : new AddressViewModel() { Name = userAddr.Name }; } }

이제, 위에서 정의한 mapper 를 다음과 같이 호출할 수 있다.

UserDTO userDTOObj = new UserDTO() { Address = new AddressDTO() { Name = "Address of the user" } }; UserViewModel user = userDTOObj.ToViewModel(); // DTO 클래스를 Viewmodel 에 매핑시킨다

이 방식의 장점은, 모든 매핑 메소드들은 공통된 이름 (ToViewModel) 을 갖게 될 것이며 이는 다양한 방법으로 재사용될 수 있을 것이다.

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 48.14: 확장 메소드를 통한 강력한 형식 (strongly typed) 의 래퍼 (wrapper) 작성하기

확장 메소드를 이용하면 Dictionary 와 유사한 객체들에 대한 강력한 형식 (strongly typed) 기반의 래퍼 (wrapper) 를 작성할 수 있다. 예를 들면 캐시라던가, HttpContext.Items 등등이 이에 해당한다.

public static class CacheExtensions { public static void SetUserInfo(this Cache cache, UserInfo data) => cache["UserInfo"] = data; public static UserInfo GetUserInfo(this Cache cache) => cache["UserInfo"] as UserInfo; }

이러한 접근 방식은 코드 전반에 걸쳐 스트링 리터럴을 키 (key) 로 사용한다거나 값을 읽을 때 원하는 타입으로의 캐스팅을 해야 한다거나 하는 필요를 없애준다. 종합적으로 보면, 이는 Dictionary 와 같은 느슨한 형식 (loosely typed) 을 갖는 객체를 보다 안전하고 강력한 형식 (strongly typed) 기반으로 사용할 수 있는 방법을 제공한다.

본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

Section 48.13: IList<T> 에 대한 확장 메소드 예제 - 2 개의 List 비교하기

아래의 확장 메소드를 이용하면 동일한 타입을 갖는 두개의 IList< T > 에 대해 내용물 기반의 비교를 수행할 수 있다.

기본적으로는 list 내의 각 요소들은 그 순서와 요소 자체를 기반으로 비교가 이루어지지만, isOrdered 파라미터에 false 를 넘기면 순서와 상관없이 요소들 자체만으로 비교가 이루어질 것이다.

이 메소드가 정상 동작하려면, 제네릭 타입 TEqualsGetHashCode 메소드를 재정의 (override) 하고 있어야 한다.

사용 예제:

List < string > list1 = new List < string > { "a1", "a2", null, "a3" }; List < string > list2 = new List < string > { "a1", "a2", "a3", null }; list1.Compare(list2); // 이 결과는 false 가 될 것이다 list1.Compare(list2, false); // 이 결과는 true 가 될 것이다. 두 리스트는 순서를 배제할 경우 동일하다

메소드 선언:

public static bool Compare < T > (this IList < T > list1, IList < T > list2, bool isOrdered = true) { if (list1 == null && list2 == null) return true; if (list1 == null || list2 == null || list1.Count != list2.Count) return false; if (isOrdered) { for (int i = 0; i < list2.Count; i++) { var l1 = list1[i]; var l2 = list2[i]; if ( (l1 == null && l2 != null) || (l1 != null && l2 == null) || (!l1.Equals(l2))) { return false; } } return true; } else { List < T > list2Copy = new List < T > (list2); // Dictionary 를 이용해 O(n^2) 복잡도로 계산하지 않고도 구현할 수 있을것이다 for (int i = 0; i < list1.Count; i++) { if (!list2Copy.Remove(list1[i])) return false; } return true; } }
본 문서는 C# Notes for Professionals (라이센스:CC-BY-SA) 를 한글로 번역한 문서입니다. 번역상 오류가 있을 수 있으므로 정확한 내용은 원본 문서를 참고하세요.

[출처] https://books.goalkicker.com/CSharpBook/

반응형

+ Recent posts