web-dev-qa-db-ja.com

プライベート静的メソッドを使用する利点

通常、インスタンスフィールドを使用する必要のないコードの重複を減らすために、内部プライベートメソッドを持つクラスを作成する場合、メソッドを静的として宣言することでパフォーマンスやメモリの利点はありますか?

例:

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()メソッドを静的として宣言する利点はありますか?ご意見はお寄せください。意見があります。

192
NerdFury

FxCopルールページ から:

メソッドを静的としてマークすると、コンパイラはこれらのメンバーに非仮想呼び出しサイトを発行します。非仮想呼び出しサイトを発行すると、現在のオブジェクトポインターがnullでないことを保証する各呼び出しの実行時のチェックが防止されます。これにより、パフォーマンスに敏感なコードの測定可能なパフォーマンス向上が得られます。場合によっては、現在のオブジェクトインスタンスへのアクセスの失敗は、正確性の問題を表します。

203
Scott Dorman

クラスを作成するとき、ほとんどのメソッドは2つのカテゴリに分類されます。

  • 現在のインスタンスの状態を使用/変更するメソッド。
  • 現在のオブジェクトの状態を使用/変更しないが、他の場所で必要な値を計算するのに役立つヘルパーメソッド。

静的メソッドは便利です。なぜなら、そのシグネチャを見るだけで、呼び出しが現在のインスタンスの状態を使用または変更しないことがわかるからです。

次の例をご覧ください。

public class Library 
 {
 private static Book findBook(List <Book> books、string title)
 {
 //ここにコードがあります
} 
}

ライブラリの状態のインスタンスがめちゃくちゃになり、その理由を解明しようとしている場合、その署名からだけで、findBookを犯人として除外できます。

メソッドまたは関数の署名を使用してできる限り通信するようにしますが、これはそのための優れた方法です。

86
Neil

静的メソッドの呼び出しはMicrosoft中間言語(MSIL)の呼び出し命令を生成しますが、インスタンスメソッドの呼び出しはcallvirt命令を生成し、nullオブジェクト参照もチェックします。 ただし、ほとんどの場合、2つのパフォーマンスの違いは重要ではありません。

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

78
Marek Takac

はい、コンパイラは暗黙のthisポインタをstaticメソッドに渡す必要はありません。インスタンスメソッドで使用しない場合でも、渡されます。

14
Kent Boogaart

このパラメーターは渡されないため、少し速くなります(ただし、メソッドの呼び出しのパフォーマンスコストは、おそらくこの節約よりもかなり高くなります)。

私がプライベート静的メソッドについて考えることができる最良の理由は、それがあなたが誤ってオブジェクトを変更できないことを意味することだと思います(このポインタがないので)。

5
Free Wildebeest

これにより、関数が静的としても使用するクラススコープのメンバーを宣言することも忘れずにすれば、インスタンスごとにこれらのアイテムを作成するメモリを節約できます。

4
Joel Coehoorn

プライベートメソッドが本当に不可能でない限り、すべてのプライベートメソッドが静的であることを非常に好みます。私は次を好むでしょう:

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個のプライベートヘルパーメソッドで終わるため、セマンティックに意味のある方法でステップのサブセットをカプセル化する新しいクラスにそれらを本当に引き出したいと思います。

ロギングが必要であり、Webサービスに通知する必要があるためにMyClassがさらに依存関係を取得する場合(決まり文句の例はご容赦ください)、どのメソッドがどの依存関係を持っているかを簡単に確認することは非常に役立ちます。

R#のようなツールを使用すると、いくつかのキーストロークでプライベート静的メソッドのセットからクラスを抽出できます。すべてのプライベートヘルパーメソッドがインスタンスフィールドに密結合しているときに試してみてください。かなり頭痛の種になることがわかります。

2
sara