top of page

C#에서 확장 메서드를 작성하는 방법

.NET(닷넷)의 확장 메서드는 C# 및 객체 지향 프로그래밍(OOP, Object Oriented Programming)의 핵심 요소입니다. C#의 확장 메서드를 사용하면 클래스, 인터페이스, 구조체 등 기존 타입의 원래 코드를 수정하지 않고도 해당 타입을 "확장"할 수 있습니다.


c# engineer

이 기능은 타사 라이브러리의 유형이나, string과 List<T> 등과 같은 기본 제공 .NET 유형처럼 소유하지 않거나 변경할 수 없는 유형에 새로운 기능을 추가하려는 경우에 특히 유용 합니다.


이 글에서는 클래스, 서드파티 및 시스템 클래스에 확장 메서드를 추가하는 방법을 알아보겠습니다.


목차



DateTime 확장 메서드를 만드는 방법


기존 DateTime 클래스와 함께 사용할 수 있는 몇 가지 메서드가 필요하다고 가정해 보겠습니다 . 예를 들어, 주어진 DateTime 객체가 주말인지 아니면 다른 것인지를 반환하는 메서드가 필요할 수 있습니다.


확장 메서드는 본질적으로 확장하려는 유형의 인스턴스 메서드인 것처럼 정적 메서드를 호출할 수 있게 해주는 구문적 편의 기능이므로 정적 클래스에서 정의해야 합니다.


확장 메서드는 다음과 같은 이유로 정적 클래스에 있어야 합니다:


  • 객체 불필요: 확장 메서드를 사용하기 위해 객체를 생성할 필요가 없습니다. 이 메서드는 기존 유형(예: string)에 새로운 기능을 추가하므로 클래스 인스턴스 없이도 작동할 수 있습니다.


  • 체계적인 코드: 정적 클래스에 확장 메서드를 추가하면 코드가 깔끔하게 정리됩니다. 관련 메서드를 그룹화하고 적절한 네임스페이스를 사용하여 코드에 쉽게 추가할 수 있습니다.


따라서 정적 클래스를 사용하면 원래 코드를 변경하지 않고도 기존 유형에 유용한 메서드를 추가할 수 있으며, 이를 호출하기 위한 객체도 필요하지 않습니다.


먼저 DateTimeExtensions 정적 클래스를 만들어 보겠습니다.


여기에는 우리가 만들고자 하는 모든 DateTime의 확장 기능이 포함됩니다 .


설명:

public static bool IsWeekend: 이 구문은 true / false를 반환하는 IsWeekend라는 정적 메서드임을 정의합니다 .bool


this DateTime date: 메서드 인수로 this 키워드를 사용하는 것은 해당 메서드가 확장 메서드임을 나타냅니다. 즉, 해당 메서드가 DateTime 클래스의 확장 메서드가 됨을 의미합니다.



동일 유형 확장 메서드를 체인하는 방법


확장 메서드를 다른 메서드와 연결하려면 일반적으로 확장하려는 메서드와 동일한 타입(또는 호환되는 타입)을 반환해야 합니다. 이렇게 하면 이전 메서드의 결과에 따라 다른 메서드를 호출할 수 있습니다.


위의 예에서 ToTitleCaseTrimAndAppend 메서드는 모두 문자열 값을 반환하는데, 이는 아래와 같이 확장 메서드를 체인으로 연결하여 모든 공백을 제거하고 제공된 문자열을 추가하기 전에 문자열을 제목 대소문자로 변환할 수 있음을 의미합니다.


TrimAndAppend 메서드에 두 번째 매개변수만 제공하는 점에 유의하세요. 첫 번째 매개변수는 확장 메서드가 적용된 문자열이기 때문입니다 (이전에 설명했듯이 this키워드로 표시).


확장 메서드가 다른 유형(원래 유형이나 호환되는 유형이 아닌)을 반환하는 경우, 체인으로 연결할 수 없습니다. 예를 들어 다음과 같습니다.


이 방법은 오류를 생성합니다. 메서드를 체인으로 연결할 때, 원래 변수에서 체인이 생성되는 것이 아니라 이전 메서드 호출의 반환 형식에서 체인이 생성됩니다.


여기에는 Boolean 값을 반환하는 IsWeekend() 라는 함수가 있습니다 . 그런 다음 Boolean 결과값으로 존재하지 않는, DateTime의 확장 함수인, AddDays(1) 함수를 호출하려고 했습니다. 그러므로, 코드 컴파일러가 빌드에 실패하고 오류를 발생시켜 알려줍니다.



인스턴스를 체인으로 반환하는 방법


일부 확장 메서드, 특히 구성(의존성 주입, 또는 디펜던시 인젝션 등) 메서드에서는 메서드 체이닝을 위해 동일한 인스턴스를 반환합니다. 이를 통해 여러 호출에서 원본 객체 또는 수정된 상태를 계속 사용할 수 있어 유연한 인터페이스를 구현할 수 있습니다.


자동차 목록의 예를 들어보겠습니다.


이제 이러한 확장 메서드에서 리스트를 반환했으므로 같은 리스트에 추가 메서드를 연결할 수 있습니다. 예를 들어, RemoveDuplicates()를 사용하여 중복을 제거한 후 같은 목록에서 바로 AddRangeOfItems()를 호출할 수 있습니다.


그러면 다음과 같이 할 수 있습니다:


자동차 브랜드 목록에서 중복 항목을 제거하고 같은 목록에 새로운 아이템을 추가했습니다. 이 작업은 RemoveDuplicates로 리스트를 반환하여 AddRangeOfItems와 연결할 수 있기 때문에 효과적입니다 .


RemoveDuplicates 리스트 대신 void를 반환하면, 메서드를 연결할 수 없습니다. 중복 항목은 제거되지만, 새 아이템을 추가하는 것과 같은 추가 작업은 같은 표현식에서 불가능합니다.



왜 내 클래스에 이런 메서드를 추가할 수 없나요?


해당 메서드가 클래스 기능의 핵심 부분이 아닌 경우 확장 메서드에 넣으면 클래스의 집중도를 높이고 유지 관리가 용이해집니다.


  • 관심사 분리: 확장 메서드를 사용하면 코드를 더 깔끔하게 유지하고 복잡성을 줄이는 데 도움이 됩니다 . 자주 사용되지 않는 메서드로 클래스가 비대해지는 것을 방지하는 데 도움이 됩니다.


  • 외부 라이브러리 강화: 소스 코드를 수정할 수 없는 라이브러리나 프레임워크를 사용하는 경우, 확장 메서드를 사용하면 정의를 변경하지 않고도 해당 유형에 기능을 추가할 수 있습니다.


System.IO 네임스페이스의 FileInfo 클래스를 사용하여 파일 작업을 한다고 가정해 보겠습니다. 파일이 너무 큰지(예: 1GB 이상) 쉽게 확인할 수 있는 메서드를 추가하고 싶을 수 있지만, 해당 클래스는 System.IO 네임스페이스에 속하기 때문에(즉, .Net에 내장되어 있기 때문에) FileInfo 클래스를 직접 수정할 수 없습니다.


확장 미사용:


확장 사용:

파일이 1GB보다 큰지 확인하는 확장 메서드를 추가하면 재사용성을 높일 수 있습니다.


이제 FileInfo 객체에 직접 IsFileTooLarge 메서드를 사용하여 코드를 더 깔끔하게 만들 수 있습니다.


서드파티 라이브러리와 패키지를 확장하면 코드의 호환성이 훨씬 높아질 수 있습니다.


  • 더 나은 구성 및 가독성: 기능이나 컨텍스트에 따라 확장 메서드를 정적 클래스로 구성하여 찾고 사용하기 쉽게 만들 수 있습니다. 확장 메서드를 체이닝할 수 있도록 하면 이러한 기능이 확실히 향상됩니다.



확장 프로그램을 사용해야 하는 경우


  • 유틸리티 메서드의 경우: 유형에 유용하지만 유형 자체에 직접 속하지 않는 유틸리티 메서드가 있는 경우(예: 서식 지정, 유효성 검사).


  • 빌트인 타입을 강화: 빌트인 타입(예 string: 또는 DateTime)을 수정하지 않고 기능을 추가하려는 경우입니다.


  • 메서드를 선택 사항으로 유지하고 싶은 경우: 사용자가 기본 클래스 디자인에 통합하도록 강요하지 않고도 사용할 수 있는 추가 메서드를 제공하려는 경우.


예시 시나리오:

사람의 이름을 보기 좋게 포맷하는 메서드를 추가하려는 Person 클래스 가 있다고 가정해 보겠습니다 .



GetFullName 확장 메서드를 사용하면 Person 클래스를 단순하게 유지하고 핵심적인 책임에 집중하면서도 유용한 기능을 제공할 수 있습니다.



확장 메서드를 사용하지 않는 경우


  • 핵심 기능의 경우: 메서드가 클래스의 핵심 동작에 필수적인 경우 해당 메서드는 확장이 아닌 클래스 자체의 일부가 되어야 합니다.


  • 긴밀한 결합의 경우: 확장 메서드에 클래스의 개인 상태에 대한 심층적인 지식이 필요하거나 내부 논리에 정기적으로 액세스해야 하는 경우입니다.


  • 공개 API의 경우: 공개 라이브러리나 API를 설계할 때 사용자가 확장 메서드를 찾거나 생성하도록 하는 것보다 필요한 메서드를 클래스에 직접 포함하는 것이 더 나은 경우가 많습니다.



확장 프로그램을 디자인할 때 고려해야 할 사항


확장 메서드는 많은 경우 강력하고 편리하지만, 확장 메서드를 사용하는 것이 최선의 선택이 아닐 수 있는 단점이나 상황도 있습니다.


숨겨진 행동/혼란

  • 확장 메서드는 클래스 정의에 직접 나타나지 않으므로 사용 가능한 확장에 익숙하지 않은 개발자는 이를 발견하기 어려울 수 있습니다.


  • 개발자는 이러한 확장 메서드가 존재한다는 사실을 알아야 합니다. 그렇지 않으면 IntelliSense와 같은 기능이 있는 IDE(예: Visual Studio, JetBrains Rider)에서 작업하지 않는 한, 해당 메서드를 사용하지 못할 수 있습니다. 이러한 IDE는 적절한 형식을 감지할 때 다른 파일이나 네임스페이스에서 확장 메서드를 제안할 수 있습니다. 기능이 풍부한 IDE가 없다면 개발자는 확장 메서드를 알고 있거나 해당 메서드가 저장된 폴더를 찾아야 합니다.


비공개 멤버에 접근 불가능

  • 확장 메서드는 public 또는 internal 인 멤버(메서드, 속성, 필드)에만 액세스할 수 있습니다.


  • 확장 메서드는 클래스 외부에서 클래스의 일부인 것처럼 동작하기 때문에 클래스의 private 또는 protected 멤버에 액세스할 수 없습니다. 이는 클래스 외부에서 메서드를 호출하는 일반 메서드와 유사합니다.


예:



코드 중복 및 과도한 사용


  • 경우에 따라 확장 메서드는 코드 중복을 유발할 수 있습니다. 여러 프로젝트나 클래스에 유사한 확장 메서드가 필요한 경우, 동일한 확장 메서드를 여러 곳에 작성하거나 복사하게 되어 코드의 일관성 있는 관리 및 업데이트가 어려워질 수 있습니다.

이를 방지하려면 코드를 효과적으로 정리하세요. 모든 확장 프로그램을 가장 상부에 가까운 확장 프로그램 폴더나 프로젝트에 보관하는 것이 좋습니다(애플리케이션에서 사용되는 디자인 패턴에 따라 달라질 수 있습니다).

  • 확장 기능 남용: 과도하게 사용하면 전역으로 사용할 필요가 없는 메서드까지 전역 공간에 가득 차게 됩니다. 이로 인해 해당 유형의 API가 오염되어 클래스의 핵심 내용과 확장 기능을 통해 추가된 내용을 구분하기 어려워질 수 있습니다.


어떤 경우에는 확장 메서드를 통해 기능을 추가하는 것보다 별도의 도우미 클래스나 서비스에 기능을 캡슐화(encapsulate)하는 것이 더 좋습니다.



결론


확장 방법은 깔끔하고 모듈화된 방식으로 기능을 추가하는 데 유용하지만 혼란, 네임스페이스 충돌, 비공개 멤버에 대한 접근 부족 등의 문제가 발생할 수도 있습니다.


이 글 전반에 걸쳐 강조되었듯이, 이 클래스들은 다양한 용도로 사용되며, 효과적으로 사용하면 .NET(닷넷)의 매우 유용한 기능이 될 것입니다. 적절한 경우에 사용해야 하지만, 클래스 자체에 속하는 기능을 대체하는 용도로 사용해서는 안 됩니다.

pngegg (11)_result.webp

<Raank:랑크 /> 구독 하기 : Subscribe

감사합니다! : Thanks for submitting!

©2024 by <Raank:랑크 /> Knowledge is Power

  • Linkedin
  • Knowledge Arcadia - Icon 8c
  • Raanktone - Icon 16 - 1
  • Qubitronix
  • Naver Blog
bottom of page