[c#] C #에서 확장 메서드로 클래스 메서드를 재정의하는 방법이 있습니까?

확장 메서드로 클래스의 메서드를 재정의하려는 경우가있었습니다. C #에서 할 수있는 방법이 있습니까?

예를 들면 :

public static class StringExtension
{
    public static int GetHashCode(this string inStr)
    {
        return MyHash(inStr);
    }
}

이 작업을 수행하고 싶었던 경우는 문자열의 해시를 데이터베이스에 저장하고 문자열 클래스의 해시 (예 : 사전 등)를 사용하는 모든 클래스에서 동일한 값을 사용할 수 있도록하는 것입니다. 기본 제공 .Net 해싱 알고리즘은 프레임 워크의 한 버전에서 다음 버전으로의 호환성이 보장되지 않습니다.이 알고리즘을 내 것으로 교체하고 싶습니다.

확장 메서드로 클래스 메서드를 재정의하려는 다른 경우도 있으므로 문자열 클래스 또는 GetHashCode 메서드에만 국한되지 않습니다.

기존 클래스에서 서브 클래 싱하여이 작업을 수행 할 수 있다는 것을 알고 있지만 많은 경우 확장 기능을 사용하여 수행 할 수 있으면 편리합니다.



답변

아니; 확장 방법은 다형성에 참여 (결코 적합한 서명 인스턴스 메소드에 우선하지 않으며 결코 GetHashCodeA는 virtual방법).


답변

메서드에 다른 서명이 있으면 수행 할 수 있습니다. 따라서 귀하의 경우 : 아니요.

그러나 그렇지 않으면 원하는 것을 수행하기 위해 상속을 사용해야합니다.


답변

내가 아는 한 대답은 ‘아니오’입니다. 왜냐하면 확장 메서드는 인스턴스가 아니기 때문입니다. 클래스의 인스턴스를 사용하여 정적 메서드를 호출 할 수있게 해주는 인텔리 센스 기능에 가깝습니다. 문제에 대한 해결책은 특정 메서드 (예 : GetHashCode ())의 실행을 가로 채고 다른 작업을 수행하는 인터셉터가 될 수 있다고 생각합니다. 이러한 인터셉터를 사용하려면 (Castle Project가 제공하는 것과 같은) 모든 개체는 다음을 사용하여 인스턴스화되어야합니다. 개체 팩토리 (또는 Castle의 IoC 컨테이너)를 사용하여 런타임에 생성 된 동적 프록시를 통해 인터페이스를 가로 챌 수 있습니다 (Caslte를 사용하면 클래스의 가상 구성원도 가로 챌 수 있음).


답변

클래스 메서드와 동일한 서명을 사용하여 확장 메서드를 호출하는 방법을 찾았지만 그다지 우아하지는 않습니다. 확장 메서드를 가지고 놀 때 문서화되지 않은 동작을 발견했습니다. 샘플 코드 :

public static class TestableExtensions
{
    public static string GetDesc(this ITestable ele)
    {
        return "Extension GetDesc";
    }

    public static void ValDesc(this ITestable ele, string choice)
    {
        if (choice == "ext def")
        {
            Console.WriteLine($"Base.Ext.Ext.GetDesc: {ele.GetDesc()}");
        }
        else if (choice == "ext base" && ele is BaseTest b)
        {
            Console.WriteLine($"Base.Ext.Base.GetDesc: {b.BaseFunc()}");
        }
    }

    public static string ExtFunc(this ITestable ele)
    {
        return ele.GetDesc();
    }

    public static void ExtAction(this ITestable ele, string choice)
    {
        ele.ValDesc(choice);
    }
}

public interface ITestable
{

}

public class BaseTest : ITestable
{
    public string GetDesc()
    {
        return "Base GetDesc";
    }

    public void ValDesc(string choice)
    {
        if (choice == "")
        {
            Console.WriteLine($"Base.GetDesc: {GetDesc()}");
        }
        else if (choice == "ext")
        {
            Console.WriteLine($"Base.Ext.GetDesc: {this.ExtFunc()}");
        }
        else
        {
            this.ExtAction(choice);
        }
    }

    public string BaseFunc()
    {
        return GetDesc();
    }
}

내가 알아 차린 것은 확장 메서드 내부에서 두 번째 메서드를 호출하면 서명과 일치하는 클래스 메서드가 있어도 서명과 일치하는 확장 메서드를 호출한다는 것입니다. 예를 들어 위 코드에서 ExtFunc ()를 호출하면 ele.GetDesc ()를 호출 할 때 예상되는 문자열 “Base GetDesc”대신 반환 문자열 “Extension GetDesc”를 얻습니다.

코드 테스트 :

var bt = new BaseTest();
bt.ValDesc("");
//Output is Base.GetDesc: Base GetDesc
bt.ValDesc("ext");
//Output is Base.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext def");
//Output is Base.Ext.Ext.GetDesc: Extension GetDesc
bt.ValDesc("ext base");
//Output is Base.Ext.Base.GetDesc: Base GetDesc

이렇게하면 원하는대로 클래스 메서드와 확장 메서드간에 앞뒤로 바운스 할 수 있지만 원하는 “범위”에 도달하려면 중복 “통과”메서드를 추가해야합니다. 더 나은 단어가 없기 때문에 여기에서 범위라고 부릅니다. 누군가가 실제로 그것이 무엇인지 알려줄 수 있기를 바랍니다.

하나 또는 두 개의 메서드가 동일한 시그니처를 가진 여러 메서드에 대한 통과 역할을 할 수 있기를 바라면서 대리자를 전달하는 아이디어도 가지고 놀았 던 “통과”메서드 이름을 추측했을 것입니다. 불행히도 델리게이트의 압축을 풀면 다른 확장 메서드 내부에서도 항상 확장 메서드 대신 클래스 메서드를 선택했습니다. “범위”는 더 이상 중요하지 않습니다. 나는 Action 및 Func 델리게이트를 많이 사용하지 않았으므로 더 경험이 많은 누군가가 그 부분을 알아낼 수있을 것입니다.


답변