2011-10-24 12 views
19

私はC#にはかなり新しいので、私と一緒にいてください。C#クラス - なぜ静的メソッドが非常に多いのですか?

私がC#について気づいた最初の事の一つは、多くのクラスが静的メソッド重いということです。

Array.ForEach(arr, proc) 

代わりに:たとえば...

なぜそれがある

arr.ForEach(proc) 

そして、なぜそれがある:

Array.Sort(arr) 

の代わり:

arr.Sort() 

ネット上のよくある質問を教えてください。詳細な回答がどこかの本のどこかにある場合、私はそれを指すポインタを歓迎します。私はこれについての決定的な答えを探していますが、あなたの推測は大歓迎です。

答えて

8

this answerが正しいと仮定すると、インスタンスメソッドは "メソッドテーブル"に追加のスペースを必要とします。配列メソッドを静的にすることは、省スペースの早期決定であったかもしれません。

これは、Amitdが参照しているポインタチェックを避けることと並んで、アレイと同じようなものとして大きな性能向上をもたらす可能性があります。

+0

リンク先の質問/回答は私が探していたものです。ありがとう!私は数分前に 'List'を発見しました。そのクラスは私が期待していた方法で動作します。そこでの答えは、なぜ配列とリストが異なるように設計されているかを示しています。 – dharmatech

+0

実際、管理者の1人がリンク先の質問の複製としてこれをマークしたい場合、それは私にとっては問題ありません。 – dharmatech

11

これらはユーティリティクラスであるためです。クラスの構築は、C#で空き関数がないことを考慮して、それらをグループ化する単なる方法です。

+0

私は 'Array'をユーティリティクラスと呼んでいません。それは、すべての配列が派生する抽象基本クラスです...これらのインスタンスメソッドを作成するのは良い場所のようです。これは良い質問だと思う。 – Daniel

+0

@Daniel多分Arrayはそれ自体はユーティリティクラスではありませんが、静的メソッドはそれがグループ化されたユーティリティメソッドのように見えます。 – Christian

+0

彼らは明らかに独自のオブジェクトへの参照を取っているので、実際にメソッドでなければならないかもしれませんが、おそらく拡張メソッドに変更することができますが、これはコスト/利益があまりにも低いかもしれません –

0

Arrayクラスは一般的ではなく、下位互換性を損なう可能性があるため、完全に汎用的にすることはできません。配列にIList<T>が実装されているところにはいくつかの魔法がありますが、それは0の「list-ish」配列の下限を持つ1次元配列に対してのみです。

私は、静的メソッドは、上記のコンパイラマジックに適格であるかどうかにかかわらず、配列の任意の形状に作用するジェネリックメソッドを追加する唯一の方法だと推測しています。

+1

あなたはいつもどんな配列( 'string []'、 'int []'など)を 'Array'のインスタンスとして指定すると、generics_の_lackが保持しているとは思えません。 – Daniel

+0

@Daniel:私の指摘は、配列には要素の型を特徴とする*インスタンスメソッドはありません。 'List 'そのようなこと - これは私に "ユーティリティ関数"の説明が水を保持していないと思います。だから、配列は何とか "特別な"ようです。 "特殊性"は、シグネチャ - *ジェネリック*メソッドの受信側の型パラメータを持つインスタンスメソッドがないため、私の結論は、一般的な場合の配列は一般的ではないということです。 – millimoose

1

静的に対する古典的な動機:

  1. スレッドセーフではありません
  2. がメモリに

1のコードサイズを大きくし

  • をテストするハード)C#はテストを行う可能ないくつかのツールを持っています静的メソッドは比較的簡単です。 https://stackoverflow.com/questions/64242/rhino-mocks-typemock-moq-or-nmock-which-one-do-you-use-and-why

    2)C#でスレッドの安全性を失うことなく静的オブジェクトの作成/ロジックを実行する方法はよく知られています。たとえば、C#で静的クラスを持つシングルトンパターンを実装する場合(不十分なオプションがボアした場合、5番目のメソッドにジャンプすることができます)3)@ K-balloには、すべてのメソッドがメモリ内のコードサイズに寄与しますC#では、特別な扱いを受けるインスタンスメソッドではなく、

    あなたが指摘した2つの具体的な例は、静的なArrayクラスのレガシーコードサポートの問題に過ぎず、ジェネリックスや他のコードの砂糖はC#1.0で紹介されていました。おそらく外部の図書館を含めて、あなたが指していたより多くのコードがあると仮定して、私は答えようとしました。

  • +2

    フレームワークメソッドをテストするのはなぜですか?あなたは質問に答えるのか、コード内に静的メソッドを定義するかどうかについて話していますか? – manojlds

    +1

    質問はなぜC#で、なぜそう多くのフレームワークではなく、非常に多くの静的に質問した。 2つの例は非常に古い、よくテストされたフレームワークメソッドでしたが、私はその質問がC#ライブラリと一般的なコードに関するものだと仮定しました。また、新しいフレームワークメソッドがあることを指摘し、コードが期待どおりに機能しないときに独自のテストを書く価値があるかもしれません。マイクロソフトのすべてがバグフリーではありません。 –

    1

    知覚される機能。

    "ユーティリティ"機能は、OOが対象とする機能の多くとは異なります。

    コレクション、I/O、数学、まさにすべてのユーティリティを使ってケースを考えてみましょう。

    OOでは、通常、ドメインをモデル化します。あなたのドメインに本当にフィットするものはありません。あなたがコーディングして "ああ、新しいハッシュテーブルを注文する必要があります、私たちはいっぱいになっています"というようなものではありません。ユーティリティのものはしばしば適合しません。

    私たちはかなり近づいていますが、コレクションを渡すことはまだあまりありません(ビジネスロジックはどこにありますか?あなたのコレクションを操作するメソッドはどこに置かれていますか?それで?)

    数字と数は同じです。 Integer.sqrt()とLong.sqrt()とFloat.sqrt()を持つのは難しいです。ちょうど意味をなさないだけでなく、「新しいMath()。sqrt()」もありません。それだけでよくモデル化しない領域がたくさんあります。あなたが数学的なモデリングを探しているなら、OOはあなたの最善の策ではないかもしれません。 (私はJavaでかなり複雑な "Complex"と "Matrix"クラスを作ってかなりOOにしましたが、OOとJavaの限界のいくつかを教えてくれました - ほとんどGroovyのクラスを "Using"

    ビジネスロジックをモデル化するためにOOほど優れているとは思えませんでした。コード間の接続を実証し、データとコードの関係を管理することができます。

    私たちはそうするのがより理にかなったら、別のモデルに戻ってしまいます。また

    5

    インスタンスのデータにアクセスしたり、インスタンスメソッドを呼び出すことはありません

    メンバーは staticとしてマークすることができFXCOP

    CA1822: Mark members as static

    規則の説明から、このルールを参照してください(Visual BasicではShared) 。 メソッドを静的としてマークすると、コンパイラは非仮想呼び出しサイトを これらのメンバーに送信します。非仮想呼び出しサイトを発行すると、現在のオブジェクトポインタ がnullでないことを確認する呼び出しごとに、 ランタイムでのチェックが実行されなくなります。これにより、パフォーマンス重視のコード の測定可能なパフォーマンスが向上します。場合によっては、現在のオブジェクトインスタンス にアクセスできないことが正しい問題を表しています。

    関連する問題