2012-12-28 9 views
9

최근에 확장 메서드를 사용하여 내가 제어하는 ​​클래스에 도우미 유틸리티를 구현하는 아이디어를 가지고 놀았습니다 (즉, 같은 프로그램에 있으며 수정). 그 뒤에있는 이론적 근거는 여러 번 사용되는 헬퍼 유틸리티가 매우 특정한 시나리오에서 사용되고 클래스 내부 값에 액세스 할 필요가 없다는 것입니다.수정할 수있는 클래스에 확장 메서드를 사용할 수 있습니까?

예를 들어 StackExchange 클래스가 있다고 가정 해 보겠습니다. PostQuestionSearchAnswerQuestion과 같은 메소드가 있습니다.

이제 StackOverflow가 나를 속일 수 없도록 내 평판을 수동으로 계산하고 싶습니다. 나는의 라인을 따라 뭔가 구현하는 것 : 나는 StackExchange 클래스에 메서드를 추가 할 수

int rep=0; 
foreach(var post in StackExchangeInstance.MyPosts) 
{ 
    rep+=post.RepEarned; 
} 

을하지만, 어떤 내부를 필요로하지 않으며, 단지 프로그램의 하나 개 또는 두 개의 다른 부분에서 사용된다 .

대신에 이러한 특정 도우미 메서드가 10 개 또는 20 개있는 경우를 상상해보십시오. 특정 시나리오에서는 유용하지만 일반적인 경우에는 분명히 아닙니다. 내 생각은

namespace Mynamespace.Extensions.RepCalculations 
{ 
    public static RepCalcExtensions 
    { 
    public static int CalcRep(this Stackexchange inst){...} 
    } 
} 

주 네임 스페이스 같은 것으로

public static RepCalcHelpers 
{ 
    public static int CalcRep(StackExchange inst){ ... } 
} 

같은 것을 변화하고 있습니다. 특정 시나리오 내에서 확장 방법을 그룹화하는 데 이상적으로 사용합니다. 예를 들어, "RepCalculations", "Statistics"등

이 유형의 패턴이 전혀 들리지 않았으며 클래스 이외의 용도로 사용되는 확장 메서드의 증거를 찾지 못했습니다. 당신은 수정할 수 없습니다.

"패턴"에는 어떤 단점이 있습니까? 대신에 상속 또는 구성에 충실해야 하는가 아니면 이걸위한 정적 헬퍼 클래스가 좋은가?

+0

확장 메서드는 원래 클래스를 수정할 수 없을 때 사용하기위한 메서드입니다. 당신이 클래스를 구현하는 사람이라면, 나는 부가가치를 보지 못한다. 메소드를 별도의 코드 파일에 넣으려면'partial' 키워드를 사용할 수 있습니다. –

+0

명확히하기 위해, 당신은 이것을 할 것입니다. 그래서 여러분은 edge-case 확장 메소드를 보유하고있는 특정'using' 문을 포함하지 않음으로써 특정 기능을 숨길 수 있습니다. ?? 매우 흥미로운! –

+0

확장 메소드의 장단점을 지정하는 [this] (http://stackoverflow.com/a/551600/649524) 링크를 확인할 수 있습니다. – Tilak

답변

4

확장 메서드에 대한 프레임 워크 디자인 지침 섹션을 읽었을 것입니다. Here은 제 2 판의 저자 중 한 사람의 게시물입니다. (특수 도우미 메서드)을 설명하는 사례는 Phil Haack이 확장 메서드의 유효한 용도로 인용 한 것으로, 이러한 숨겨진 메서드를 찾기 위해 API에 대한 추가 지식이 필요하다는 단점이 있습니다.

해당 게시물에 언급되어 있지는 않지만 확장 메서드는 확장 클래스에서 별도의 네임 스페이스로 이동한다는 점에서 권장됩니다. 그렇지 않으면, 그들은 항상 인텔리 센스와 함께 나타나고 그들을 끌 수있는 방법이 없습니다.

+0

글쎄, 일관성 나는 그 (것)들을 발견 가능하게하기를위한 당신의 친구다고 추정한다. 평범한'.Extensions. *'네임 스페이스를 갖는다면 꽤 쉬울 것입니다. – Earlz

+0

@ Earlz Consistency는 분명히 장점입니다. 유용하게 사용할 수있는 많은'using' 문을 추가하지 않아도된다는 것을 나는 압니다. –

+0

글쎄, 문장을 사용하여 2 개 이상의 확장을 추가하는 것이 결코 바람직하지 않기 때문에 확장이 그룹화 된 방법의 균형을 맞추기가 어려울 수 있습니다. – Earlz

0

나는이 패턴을 다른 곳에서 본 것으로 생각합니다. 그것은 꽤 혼란 스럽지만 꽤 강력 할 수도 있습니다. 그렇게하면 별도의 네임 스페이스에서 라이브러리의 클래스와 확장 메서드 집합을 제공 할 수 있습니다. 그런 다음 라이브러리를 사용하는 사용자는 확장 메소드를 사용하여 네임 스페이스를 가져 오거나 자체 확장 메소드를 제공 할 수 있습니다.

단위 테스트에만 사용되는 확장 메소드가있는 경우 (예 : 단위 테스트에만 필요하다는 의미로 두 객체가 동일한 지 비교하는 경우)이 패턴의 좋은 후보가 될 수 있습니다.

0

확장 메서드가 public 인스턴스 메서드와 동일하다는 비교를하는 것처럼 보입니다. 정말로 그렇지 않습니다.

확장 메서드는 public static 유틸리티 메서드이며 호출되는 데 편리한 구문을 사용합니다.

그래서 먼저이 메소드가 클래스 자체의 인스턴스 메소드가되는 것이 적절하거나 외부 클래스의 정적 메소드가되는 것이 더 적절해야합니다. 매우 소수의 사용자가이 기능을 필요로한다는 사실은 고도로 지역화되어 있으며 클래스 자체가 수행하는 동작이 아니라 외부 엔터티가 클래스에서 수행하는 동작이 정적 인 것이 적절하다는 것을 의미합니다. 가장 큰 단점은 누군가가 User을 가지고 있고 담당자를 다시 계산하려는 경우 찾을 가능성이있는 행동입니다. 자,이 특별한 경우 울타리에 조금 있습니다, 당신은 다른 길로 갈 수 있지만 정적 방법으로 기울고 있습니다.

이제는 정적이어야한다고 결정 했으므로 확장 방법인지 여부에 대한 완전히 별개의 질문입니다. 이것은 훨씬 더 주관적이며 개인 선호 영역으로 들어가게됩니다. 메서드가 연결될 가능성이 있습니까? 그렇다면 확장 메서드는 정적 메서드에 대한 중첩 호출보다 훨씬 효율적으로 연결됩니다. 그것을 사용하는 파일에서 많이 사용 될 가능성이 있습니까? 그렇다면 확장 메서드가 코드를 단순화하는 경향이 있습니다. 아니라면 실제로 코드가 도움이되지 않습니다. 장난감 예제에서는 아마도 개인적으로는 안된다고 말할 것입니다.하지만 누군가와 전혀 문제가되지 않을 것입니다 (결국 확장 메서드를 일반 공용 정적 메서드 구문과 같이 사용할 수는 있습니다.). 비 장난감 사례의 경우 대부분 사례별로 결정됩니다. 요점은 어떤 클래스를 확장할지주의 깊게 살펴보고, 사용자가 메서드의 호출을 약간 더 편리하게하기 위해 Intellisense를 혼란스럽게 할지를 스스로 물어 보는 것입니다 (이 방법은 사용 된 파일 당 사용되는 양이 다시 계산됩니다. 에서).

확장 메서드가 인스턴스화 된 메서드보다 강력한 일 수있는 몇 가지 단점도 있습니다. 특히 유형 유추를 활용합니다. 정규 인스턴스 메소드를 사용하면 해당 유형의 유형 또는 모든 하위 유형을 받아 들일만큼 쉽지만 때로는 상위 유형 대신 전달 된 유형이 무엇이든지 반환하는 것이 유용합니다. 이것은 유창한 API에서 특히 사용됩니다. 이것은 매우 일반적인 예가 아니며, 단지 당신의 질문과 매우 관련이 있으므로, 나는 그것을 확장하지 않을 것입니다.

+0

전체 정적 메서드와 확장 비트 비교 :이 특정 사례의 경우 실제로 인텔리 센스를 사용한다고 가정 할 때 확장 방법이 더 쉽게 발견 될 수 있다고 생각하십시오. 먼저 Extensions 네임 스페이스에서 수행중인 작업과 관련된 항목을 살펴보고 원하는 메서드가 해당 클래스에 자동으로 추가됩니다. 정적 헬퍼 클래스를 찾아야하는 횟수, 특히 서로 다른 일관성이없는 네임 스페이스에있는 경우를 여러 번 말할 수 없습니다. – Earlz

0

확장 메서드는 클래스가 인터페이스를 구현하고 동일한 인터페이스를 구현하는 다른 "미래"클래스에서 같은 메서드를 구현하지 않아도되도록 매우 유용 할 수 있습니다. 예를 들어, StackExchange는 IStackExchange를 구현하고 ProgrammersExchange는 IStackExchange도 구현합니다. 예제 확장 메소드는 CalcRep을 한 번만 구현하고 두 클래스 모두에서 다시 구현할 필요가없는 경우에 유용합니다. 이것은 정적 Enumerable 클래스에있는 모든 확장 메서드에 대한 이유입니다.

이 외에도 이미 수정할 수있는 클래스에서 확장 메서드를 사용해야하는 강력한 이유는 없습니다. 어떤 것이 든 그것은 과부하 해결 과정에서 늦게 고려되는 단점이 있습니다.

+0

과부하로 간주되는 도우미 유틸리티가 실제로 좋지 않다고 생각하지 않습니다. 사례. Linq, IEnumerable .Count() 확장 메서드가 있는지 확인하십시오. 그러나 IEnumerable을 구현하는 많은 것들은 전체 목록을 반복하는 것보다 훨씬 빠른 계산 방법을 가지고 있습니다. – Earlz

+0

Enumerable.Count 메서드는 확장 기능으로 적합합니다. 방법을 처음 언급 한 이유가 아니라 과부하 해결에 늦었습니다. 그것이 인터페이스의 일부분 일지라도, 각 구현자는 자신의 빠른 계산 방법을 구현할 수 있습니다. –

+1

... 그리고 사실 현재 구현 된 Count() LINQ 메서드는 일부 형식 검사를 만들고 원본 열거 형이 ICollection이면 ICollection.Count로 연기합니다. 그러나 조건자를 취하는 메서드는이 검사를하지 않으며 추가 Linq 확장 끝에 Count()를 사용하면 ICollection이 아닌 IEnumerable이 전달됩니다. – KeithS

관련 문제