2009-02-23 5 views
27

共通のインターフェイスを実装するクラス のセットを開発しています。私の図書館の消費者は、これらのクラスのそれぞれが一定の静的関数のセットを実装すると期待します。とにかく、これらのクラスを飾ることができるので、コンパイラは関数の1つが実装されていないケースをキャッチします。 C#クラスに特定の静的関数を実装させる方法はありますか?

消費コードを作成するときに最終的にはキャッチされることはわかっています。そして、私はまた、一種の工場クラスを使ってこの問題を回避する方法を知っています。

クラスに静的関数を必要とする構文/属性があるかどうか不思議です。

Ed混乱を避けるために、「インターフェイス」という単語を削除しました。

+0

私の好奇心は嬉しいですが、なぜこのような機能が必要なのでしょうか?静的メソッドは、通常のインスタンス(非静的)メソッドにはないものは何ですか?私の心には何も来ません。あなたの質問にいくつかの文脈を共有したいと思っていますか? – Dan

+2

静的メソッドを呼び出すためのインスタンスは必要ありません。したがって、デシリアライズメソッドなどのファクトリメソッドとして使用するのがうれしいです。 – tpower

+0

@ダン:インスタンスやタイプを操作しているかどうか(または後で変更するかどうか)を知らなくても、インタフェースを使用することができます。何らかの種類のシングルトンリストを表す静的クラスを考えてください。適切なリストとして 'IList 'を実装する必要があります。確かに、静的クラスに 'IList 'を実装したクラスのインスタンスを保存することの回避策が実現可能です(そして、私はC#が今のところそれだけを許していることを認識しています)。しかし、静的にクラスを直接宣言する能力インタフェースを実装すると、不要なレベルの間接指定が削除されます。 –

答えて

28

いいえ、これはC#でサポートされていません。すぐに考えることができる2つの回避策があります:

  • 実行時にリフレクションを使用します。限り、あなたは単位を持っているように、メソッドに

更新)実際に

を宣言するインタフェースを実現するためにも、同様のシングルトン/デフォルト・インスタンスを/使用

  • 交差指と希望...テストの場合、最初の選択肢は、(私のように)厳密な "静的型付け"のバックグラウンドから来ると思うほど実際には悪いことではありません。事実は、動的言語でうまく動作します。確かに、これは正確に私のgeneric operatorsコードの動作 - それは期待している静的演算子があります。実行時に、そうしなければ、それはあなたを適切に嘲笑するトーンで笑います...しかし、コンパイル時にチェックすることはできません。

  • +11

    コードが適切な嘲笑調子で私を笑ったなら、私はそれが大好きです。待って、それはいつも起こるだろう。気にしないで。 ;-) –

    4

    残念ながら、いいえ、これは言語に組み込まれたようなものはありません。

    0

    いいえ、この機能には何の意味もありません。インタフェースは、基本的に、複数の継承のスケールダウンされた形式です。これらは、非静的な仮想メソッドが子孫クラスで適切に呼び出されるように仮想関数テーブルを設定する方法をコンパイラに指示します。静的メソッドは仮想にすることはできません。そのため、インタフェースを使用する意味はありません。

    +2

    メソッドがインターフェイス経由で呼び出されないからといって、そこにいることをテストする価値がないわけではありません。 C#が公開する新しいT()制約のようなものです。新しいT()の実際の実装は、リフレクションによって効果的に行われます。 –

    +0

    私はそれらを仮想化したくないだけです。 – tpower

    +0

    私はこれでdsimchaと一緒にいます。明示的に宣言されたインタフェースの目的がインプリメンテーションからインタフェースを分離しない場合、「インタフェース」はあまり残っていません。 HasToImplementMethodsAttrib – Dan

    15

    いいえ、基本的には、静的ポリモーフィズムのようなものです。これはC#では存在しませんが、私は一種の"static interface" notion which could be useful in terms of genericsを提案しました。

    1つのこと doは、特定のアセンブリのすべてのタイプがルールに従っていることを確認する簡単な単体テストを作成します。他の開発者もインターフェイスを実装している場合、インターフェイスを実装するすべてのユーザーが簡単に独自のアセンブリをテストできるように、テストコードを共通の場所に配置することができます。

    +0

    インターフェイスのすべての*正当な*実装に、特定の静的メンバ*と*がなければならないことをインタフェース契約で指定することができます。*開封された場合、すべての正当な*派生型が同じ要件を満たさなければならないという要件が継承規約に含まれます。それは人々がインタフェースの不正な実装を書くのを妨げることはありませんが、ほとんどの他の種類のインタフェースよりも悪化することはありません。 – supercat

    +0

    @supercat:「契約」とは、単に「ドキュメンテーション」またはコード契約のようなものですか? –

    +0

    私はドキュメンテーションを意味しました。意味のあるインタフェースは、それらの要件を満たす実装が正当なものであり、それらの要件を満たしていない実装が違法であるような一連の要件を持つ必要があります。このような要件を表現しなければならない固定フォーマットはありませんが、たとえば'IList 'の実装は、 'index'パラメータを無視して単純な要素を上書きするプロパティセッターを持っていました。' IList 'で動作すると期待される多くのメソッドが失敗しました。 'IList 'の実装は正当ではありませんでした。 – supercat

    3

    このための言語サポートはありませんが、静的解析ツールを使用して強制できます。たとえば、クラスの属性またはインターフェイスの実装を検出し、特定の静的メソッドの存在を確認するカスタムルールをFxCopに書き込むことができます。

    0

    Marc Gravellが提案したように、必要なものに近づけるアプローチはシングルトンです。

    インターフェイスは、とりわけ、クラスにあるレベルの抽象化を提供して、実装するタイプに関係なく指定されたAPIを使用できるようにします。しかし、静的クラスを使用するには、その静的クラスの型を知る必要があるため、そのクラスを実装して一連の関数を実装する必要があるのはなぜですか?

    [ImplementsXXXInterface]のようなカスタム属性を使用して、この属性を持つクラスが実際に必要なインターフェイスを実装していることを確認するための実行時チェックを提供することができますか?

    +0

    ランタイムチェックは、コンシューマーコードを作成するときにコンパイラーがすでに選択しているため、あまり良くありません。コンパイラに以前にそれを拾うことができるかどうかは不思議です。 – tpower

    1

    シングルトンパターンは、すべての場合に役立つわけではありません。私の例は私の実際のプロジェクトからのものです。それは人為的なものではありません。

    私はサードパーティORMのクラスから継承するクラス(「ウィジェット」と呼ぶ)を持っています。静的メソッドが宣言されていることを確認するために、ウィジェットオブジェクトをインスタンス化する(したがって、dbをローにする)場合、私はクリーンアップしようとしているものよりも大きな混乱を犯しています。

    私はデータストアにこの余分なオブジェクトを作成した場合、私は、ユーザーからそれを隠すために持っている、計算、など

    私は一連の共通機能を実装することを確認するためにC#でインタフェースを使用クラス。

    これらの機能を実装するメソッドの中には、インスタンスデータを実行する必要があるものがあります。これらのメソッドをインスタンスメソッドとしてコード化し、それらがクラスに存在することを確認するためにC#インターフェイスを使用します。

    これらのメソッドの中には、インスタンスデータを必要としないものがあるため、静的メソッドです。私が静的メソッドでインターフェイスを宣言できれば、コンパイラはこれらのメソッドがインターフェイスを実装しているクラスに存在するかどうかをチェックできます。

    5

    これは大きな質問であり、自分のプロジェクトで遭遇した問題です。

    多態性のためだけにインターフェイスと抽象クラスが存在し、強制的に特定のメソッドを実装するためのクラスはありません。個人的には、多形性が主要な使用例であり、強制的な実装が二次的なものであると考えます。私は強制的な実装方法をかなり頻繁に使用しています。通常、テンプレートパターンを実装するフレームワークコードに表示されます。基本/テンプレートクラスは複雑なアイデアをカプセル化し、サブクラスは抽象メソッドを実装することでさまざまなバリエーションを提供します。実用的なメリットの1つは、抽象メソッドがサブクラスを実装する他の開発者にガイダンスを提供することです。 Visual Studioには、メソッドをスタブする機能もあります。これは、保守開発者が数か月後に新しいサブクラスを追加する必要がある場合に特に役立ちます。

    C#では、これらのテンプレートシナリオのいくつかについて特別なサポートはないという欠点があります。静的メソッドは1つです。もう一つはコンストラクタです。理想的には、ISerializableは、開発者に保護された直列化コンストラクタを実装させる必要があります。

    最も簡単なアプローチは、自動テストを使用して静的メソッドが目的の型に実装されているかどうかをチェックすることです(前述)。既に言及されている別の実行可能なアイデアは、静的解析ルールを実装することです。

    第3のオプションは、PostSharpなどのAspect-Oriented Programmingフレームワークを使用することです。 PostSharpは、コンパイル時の側面の検証をサポートしています。コンパイル時にアセンブリに反映される.NETコードを記述して、任意の警告とエラーを生成することができます。通常、アスペクトの使用が適切であることを検証するためにこれを行いますが、テンプレートルールの検証にも使用できない理由はわかりません。

    0

    あなただけのこれらのコンパイルエラーを取得した後、この設定を検討している場合:

    1. がインタフェースのメソッドを定義します。
    2. abstractを使用してメソッドを宣言します。
    3. public staticメソッドを実装し、オーバーライドされた抽象メソッドで静的メソッドを単に呼び出すようにします。

    これは少し余分なコードですが、誰かが必要な方法を実装していないときはわかります。

    関連する問題