C # 확장 메서드로 클래스를 확장하려면 어떻게해야합니까?


98

확장 메서드를 클래스에 적용 할 수 있습니까?

예를 들어 다음과 같이 호출 할 수있는 Tomorrow () 메서드를 포함하도록 DateTime을 확장합니다.

DateTime.Tomorrow();

내가 사용할 수 있다는 걸 알아

static DateTime Tomorrow(this Datetime value) { //... }

또는

public static MyClass {
  public static Tomorrow() { //... }
}

비슷한 결과를 얻을 수 있지만 DateTime.Tomorrow를 호출 할 수 있도록 DateTime을 어떻게 확장 할 수 있습니까?

답변:


70

기존 유형이 부분으로 표시되지 않는 한 기존 유형에 메소드를 추가 할 수 없습니다 . 확장 메소드를 통해 기존 유형의 멤버로 보이는 메소드 만 추가 할 수 있습니다 . 이 경우 확장 메서드는 해당 형식의 인스턴스를 사용하므로 형식 자체에 정적 메서드를 추가 할 수 없습니다.

다음과 같은 정적 도우미 메서드를 만드는 데 방해가되는 것은 없습니다.

static class DateTimeHelper
{
    public static DateTime Tomorrow
    {
        get { return DateTime.Now.AddDays(1); }
    }
}

다음과 같이 사용합니다.

DateTime tomorrow = DateTimeHelper.Tomorrow;

6
어우? 이것이 6 개월 이내에 구현되고 Kumu 의 대답이 바로 거기에 있지 않으면 실제로 불완전 해 보입니다!
cregox

4
@Cawas 이것은 불완전하지 않습니다. Andrew는 확장 메서드가 아닌 정적 도우미를 사용하여이 작업을 수행하는 방법을 보여줍니다 (인스턴스가 없기 때문에).
Nick N.

1
당신 말이 맞아요, 닉. 그래도 확장 방법을 선호합니다! ;)
cregox 2014-08-12

2
extensionmethod.net/csharp/datetime 은 무엇입니까 ? IMHO, 학습 곡선 최소화를위한 더 나은 샘플은 전체 소스 코드 좋은 패턴과 실제 응용 프로그램입니다
Kiquenet

3
이 코드의 문제점은 DateTime 개체가 아닌 DateTime.Now에서만 작동한다는 것입니다. 유틸리티로서 전날 (또는 미래) 다음날을 결정하는 데 사용할 수 있습니다. 하지 DateTime.Now을 언급하기는 ... 당신이 그것을 호출 할 때마다 결정된다
MintGrowth

181

확장 방법을 사용하십시오 .

전의:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
            return date.AddDays(1);
        }    
    }
}

용법:

DateTime.Now.Tomorrow();

또는

AnyObjectOfTypeDateTime.Tomorrow();

2
Shuggy 의 대답 은 또한 이것을 해결하는 것과 비슷한 방식으로 약간의 빛을 파쇄했습니다.
cregox

8
'ExtensionMethods 사용'을 잊지 마십시오. 이를 위해 문서 상단에 있습니다.
Luke Alderton 2013-07-03

DateTime.Tomorrow ()를 할 수없는 이유는 무엇입니까?
lawphotog 2014-07-17

안녕하세요 lawphotog,이 확장에는 객체가 필요합니다. 여기서 DateTime은 객체가 아니라 구조체입니다.
Kumu

4
이전 주석에서 언급했듯이 (분명히 명확하지 않았습니다) DateTime.Tomorrow()클래스 및 클래스 구조체의 인스턴스에서만 작동하는 확장 메서드 로 사용할 수 없습니다 . 클래스 struc에서 정적 메서드를 "확장"하려면 Andrew의 대답 또는 Shuggy의 대답을 따르십시오 .
Alex

18

확장 메서드는 첫 번째 매개 변수가 T 유형의 인스턴스 인 정적 메서드를 T의 인스턴스 메서드 인 것처럼 보이게 만들기위한 구문 설탕입니다.

따라서 '정적 확장 메서드'를 만들면 확장 메서드보다 코드 독자를 혼란스럽게 할 수 있으므로 이점이 크게 손실됩니다 (완전한 것으로 보이지만 실제로 해당 클래스에 정의되어 있지 않기 때문입니다). 구문 상 이득이 없습니다 (예를 들어 Linq 내에서 유창한 스타일로 통화를 연결할 수 있음).

어쨌든 using을 사용하여 확장을 범위로 가져와야하므로 생성하는 것이 더 간단하고 안전하다고 주장합니다.

public static class DateTimeUtils
{
    public static DateTime Tomorrow { get { ... } }
}

그리고 다음을 통해 코드에서 이것을 사용하십시오.

WriteLine("{0}", DateTimeUtils.Tomorrow)

11

내가 답을 얻을 수있는 가장 가까운 방법은 System.Type객체에 확장 메서드를 추가하는 것입니다. 예쁘지는 않지만 여전히 흥미 롭습니다.

public static class Foo
{
    public static void Bar()
    {
        var now = DateTime.Now;
        var tomorrow = typeof(DateTime).Tomorrow();
    }

    public static DateTime Tomorrow(this System.Type type)
    {
        if (type == typeof(DateTime)) {
            return DateTime.Now.AddDays(1);
        } else {
            throw new InvalidOperationException();
        }
    }
}

그렇지 않으면 IMO Andrew와 ShuggyCoUk가 더 나은 구현을 가지고 있습니다.


이 접근 방식에는 문제가 있습니다. "typeof (...)"를 입력하는 것은 편리하지 않으며 intellisense를 사용하면 모든 유형의 확장을 볼 수 있습니다. 그래도 제가 생각하지 못했던 흥미로운 접근 방식입니다. +1.
Meta-Knight

@ Meta-Knight True, 그래서 개인적으로 다른 사람의 대답을 선호합니다. 내 대답에는 OP 질문에 가장 가까운 구문이 있지만이 문제를 해결하는 가장 좋은 방법은 아닙니다.
Adrian Godong

Type필요한 다른 유형으로 대체 할 수 있습니다. 나는 그것을 함께 사용하고 From완벽하게 작동합니다. 그래서 나는이 대답은 일반적으로하지만 올바른 생각
카시아

3

나는 Kumu와 똑같이 할 것입니다

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        public static DateTime Tomorrow(this DateTime date)
        {
           return date.AddDays(1);
        }    
    }
}

그러나 이것을 new DateTime (). Tomorrow ();

DateTime.Now.Tomorrow ();보다 더 많이 본다고 생각하십시오.


1
그리고 Kumu의 답변에 대한 의견으로 쓸 기회를 놓쳤습니다! : P
cregox

3

유형을 수정할 필요없이 새 메소드를 추가하여 기존 유형을 확장하는 기능을 제공합니다. 인스턴스 메서드 구문을 사용하여 응용 프로그램 내의 확장 된 유형의 개체에서 메서드를 호출하는 것을``확장 ''메서드라고합니다. 확장 메서드는 형식의 인스턴스 멤버가 아닙니다. 기억해야 할 요점은 정적 메서드로 정의 된 확장 메서드는 using 지시문을 통해 네임 스페이스를 애플리케이션 소스 코드로 명시 적으로 가져올 때만 범위 내에 있다는 것입니다. 확장 메서드는 정적 메서드로 정의되어 있지만 인스턴스 구문을 사용하여 호출됩니다.

여기에서 전체 예제를 확인하십시오. http://www.dotnetreaders.com/articles/Extension_methods_in_C-sharp.net,Methods_in_C_-sharp/201

예:

class Extension
    {
        static void Main(string[] args)
        {
            string s = "sudhakar";
            Console.WriteLine(s.GetWordCount());
            Console.ReadLine();
        }

    }
    public static class MyMathExtension
    {

        public static int GetWordCount(this System.String mystring)
        {
            return mystring.Length;
        }
    }

3

나는 비슷한 것을 찾고 있었다-확장 메서드를 제공하는 클래스에 대한 제약 목록. 간결한 목록을 찾기가 어려우므로 여기에 있습니다.

  1. 필드, 메서드 등의 개인 또는 보호 된 항목을 가질 수 없습니다.

  2. 에서와 같이 정적 클래스 여야합니다 public static class....

  3. 메서드 만 클래스에있을 수 있으며 모두 공용 정적이어야합니다.

  4. 기존의 정적 메서드를 사용할 수 없습니다. this 인수를 포함하지 않는 메서드는 허용되지 않습니다.

  5. 모든 방법은 시작해야합니다.

    public static ReturnType MethodName (this ClassName _this, ...)

따라서 첫 번째 인수는 항상 this 참조입니다.

이로 인해 발생하는 암시 적 문제가 있습니다. 어떤 종류의 잠금이 필요한 메서드를 추가하면 클래스 수준에서 실제로 제공 할 수 없습니다. 일반적으로 비공개 인스턴스 수준 잠금을 제공하지만 비공개 필드를 추가 할 수 없으므로 일부 외부 클래스에서 공개 정적으로 제공하는 등 매우 어색한 옵션이 남습니다. 징후는 C # 언어의 종류 이들에 대한 설계에 나쁜 차례의했다 .

해결 방법은 Extension Method 클래스를 일반 클래스에 대한 Facade로 사용하고 Extension 클래스의 모든 정적 메서드 는 Singleton을 사용하여 실제 클래스를 호출하는 것입니다 .


2

불행히도 그렇게 할 수 없습니다. 그래도 유용 할 것이라고 생각합니다. 다음을 입력하는 것이 더 자연 스럽습니다.

DateTime.Tomorrow

보다:

DateTimeUtil.Tomorrow

Util 클래스를 사용하면 하나가 아닌 두 개의 다른 클래스에 정적 메서드가 있는지 확인해야합니다.


1

자세한 설명과 함께 답변을 개선했습니다. 이제 확장 방법에 대해 더 쉽게 이해할 수 있습니다.

확장 방법 : 서브 클래스를 사용하지 않고 기존 클래스 나 구조체를 수정 또는 재 컴파일하지 않고도 기존 클래스의 동작을 확장 할 수있는 메커니즘입니다.

커스텀 클래스, .net 프레임 워크 클래스 등을 확장 할 수 있습니다.

확장 메서드는 실제로 정적 클래스에 정의 된 특수한 종류의 정적 메서드입니다.

마찬가지로 DateTime클래스는 이미 위의 촬영 때문에 우리는 설명이 클래스를 촬영하지 않았습니다.

아래는 예입니다

// 메서드가 하나만있는 기존 Calculator 클래스 (Add)

public class Calculator 
{
    public double Add(double num1, double num2)
    {
        return num1 + num2;
    }

}

// Below is the extension class which have one extension method.  
public static class Extension
{
    // It is extension method and it's first parameter is a calculator class.It's behavior is going to extend. 
    public static double Division(this Calculator cal, double num1,double num2){
       return num1 / num2;
    }   
}

// We have tested the extension method below.        
class Program
{
    static void Main(string[] args)
    {
        Calculator cal = new Calculator();
        double add=cal.Add(10, 10);
        // It is a extension method in Calculator class.
        double add=cal.Division(100, 10)

    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.