[C#] 전용 정적 메소드 사용의 장점

일반적으로 코드 중복을 줄이기 위해 내부 전용 메서드가있는 클래스를 만들 때 인스턴스 필드를 사용할 필요가없는 경우 메서드를 정적으로 선언하면 성능이나 메모리 이점이 있습니까?

예:

foreach (XmlElement element in xmlDoc.DocumentElement.SelectNodes("sample"))
{
    string first = GetInnerXml(element, ".//first");
    string second = GetInnerXml(element, ".//second");
    string third = GetInnerXml(element, ".//third");
}

private static string GetInnerXml(XmlElement element, string nodeName)
{
    return GetInnerXml(element, nodeName, null);
}

private static string GetInnerXml(XmlElement element, string nodeName, string defaultValue)
{
    XmlNode node = element.SelectSingleNode(nodeName);
    return node == null ? defaultValue : node.InnerXml;
}

GetInnerXml () 메서드를 정적으로 선언하면 어떤 이점이 있습니까? 의견이 없습니다. 의견이 있습니다.



답변

로부터 의 FxCop 규칙 페이지 이것에 :

메소드를 정적으로 표시 한 후 컴파일러는 비가 상 호출 사이트를 해당 멤버에게 내 보냅니다. 비가 상 호출 사이트를 내 보내면 각 호출에 대해 런타임시 현재 개체 포인터가 널이 아닌지 확인하지 못합니다. 이로 인해 성능에 민감한 코드의 성능이 크게 향상 될 수 있습니다. 경우에 따라 현재 객체 인스턴스에 액세스하지 못하면 정확성 문제가 발생합니다.


답변

클래스를 작성할 때 대부분의 메소드는 두 가지 범주로 나뉩니다.

  • 현재 인스턴스의 상태를 사용 / 변경하는 메소드
  • 현재 객체의 상태를 사용 / 변경하지 않지만 다른 곳에서 필요한 값을 계산하는 데 도움이되는 도우미 메서드.

정적 메서드는 서명을 살펴보면 현재 인스턴스의 상태를 사용하거나 수정하지 않는다는 것을 알기 때문에 유용합니다.

이 예제를 보자 :

공공 수업 도서관
{
    private static Book findBook (목록 <책> 책, 문자열 제목)
    {
        // 코드는 여기에 간다
    }
}

라이브러리 상태의 인스턴스가 망가 졌을 때 이유를 알아 내려고 노력하고 있다면 시그너처에서 findBook을 범인으로 배제 할 수 있습니다.

나는 메소드 나 함수의 서명으로 가능한 한 많이 의사 소통하려고 노력한다. 이것은 훌륭한 방법이다.


답변

정적 메서드를 호출하면 MSIL (Microsoft Intermediate Language)로 호출 명령어가 생성되지만 인스턴스 메서드를 호출하면 callvirt 명령어가 생성되어 null 객체 참조도 확인합니다. 그러나 대부분 두 경우의 성능 차이는 중요하지 않습니다.

src : MSDN-http://msdn.microsoft.com/en-us/library/79b3xss3(v= vs.110).aspx


답변

그렇습니다. 컴파일러는 암시 적 this포인터를 static메서드 에 전달할 필요가 없습니다 . 인스턴스 메소드에서 사용하지 않더라도 여전히 전달됩니다.


답변

이 매개 변수가 전달되지 않기 때문에 약간 빠릅니다 (메소드를 호출하는 데 드는 성능 비용은 아마도이 절약보다 훨씬 더 높습니다).

개인 정적 메소드에 대해 생각할 수있는 가장 좋은 이유는 실수로 객체를 변경할 수 없다는 것을 의미하기 때문입니다 (이 포인터가 없기 때문에).


답변

따라서 함수가 정적으로 사용하는 클래스 범위 멤버도 선언해야한다는 점을 기억해야합니다. 이렇게하면 각 인스턴스에 대해 해당 항목을 작성하는 메모리가 절약됩니다.


답변

나는 실제로 할 수 없다면 모든 개인 메소드가 정적 인 것을 매우 선호합니다. 나는 다음을 훨씬 선호한다.

public class MyClass
{
    private readonly MyDependency _dependency;

    public MyClass(MyDependency dependency)
    {
        _dependency = dependency;
    }

    public int CalculateHardStuff()
    {
        var intermediate = StepOne(_dependency);
        return StepTwo(intermediate);
    }

    private static int StepOne(MyDependency dependency)
    {
        return dependency.GetFirst3Primes().Sum();
    }

    private static int StepTwo(int intermediate)
    {
        return (intermediate + 5)/4;
    }
}

public class MyDependency
{
    public IEnumerable<int> GetFirst3Primes()
    {
        yield return 2;
        yield return 3;
        yield return 5;
    }
}

인스턴스 필드에 액세스하는 모든 메소드를 통해 왜 이런거야? 이 계산 과정이 더 복잡해지고 클래스가 15 개의 개인 도우미 메서드로 끝나기 때문에 의미있는 의미로 단계의 하위 집합을 캡슐화하는 새로운 클래스로 가져올 수 있기를 원합니다.

언제 MyClass 우리는 로깅도 (상투 예를 용서하시기 바랍니다) 웹 서비스를 통지 할 필요가 필요가 있기 때문에 더 종속성을 얻을, 그것은 쉽게 방법이있는 종속성이 무엇을보고 정말 도움이됩니다.

R #과 같은 도구를 사용하면 몇 번의 키 입력으로 일련의 개인 정적 메소드에서 클래스를 추출 할 수 있습니다. 모든 개인 헬퍼 메소드가 인스턴스 필드에 밀접하게 연결되어 있으면 상당히 어려울 수 있습니다.