2011-01-31 6 views
6

可能性の重複:私はこれを行うと
Why can't I use interface with explicit operator?なぜC#では、コンポジションを使用する型にインターフェイスの暗黙的な変換を許可しないのですか?

は:

public struct Effect 
{ 
    public IEffect IEffect { get; private set; } 

    public Effect (IEffect effect) 
    { 
     this.IEffect = effect; 
    } 

    public static implicit operator IEffect (Effect effect) 
    { 
     return effect.IEffect; 
    } 

    public static explicit operator Effect (IEffect effect) 
    { 
     return new Effect (effect); 
    } 
} 

は、私はこのようなコンパイラエラーを取得:

「をImageEditor.Effect .impインターフェイスへの、または インターフェイスへのユーザー定義の変換は許可されません。

なぜ許可されていませんか?これは良い習慣ではありませんか?

+0

可能な複製:http://stackoverflow.com/questions/2433204/why-cant-i-use-interface-with-explicit-operator –

答えて

7

これは、C#言語仕様のセクション10.10.3で詳しく説明しています。

しかしある理由の概要理由...

  • 変換演算子には、組み込みの変換を置き換えるべきではありません。これはちょうど、非常に紛らわしい行動につながることができ
  • それはインターフェイスへの暗黙的な変換が交換されたかどうかを判断することはできません一般的に
  • 変換を内蔵しており、したがって、それが主な理由は、オブジェクトということです
+0

ありがとうございました。Jaredは、2番目の理由で、「不可能」という意味ですコンパイラまたはユーザーが決定する?私はそれがユーザーだと仮定します。 –

+0

主な理由は、オブジェクトをIOneInterfaceおよびITwoInterfaceに変換できる場合、IOneInterfaceを介したオブジェクトの参照をITwoInterfaceにキャスト可能にする必要があるということです。オペレータを無効にすると、これを破ることができます。 (少なくともそれは私の理解であった) –

+1

@Joan not possibleこの決定を下すコンパイラの能力を指します。注意:コンパイラがこの決定を下すことができる特定のケース( 'struct'および' sealed'クラス)があるので、一般的なケースに限定されています。しかし、C#チームはこれに対して(私が推測できるのは推測できますが、私の推測は一貫性です) – JaredPar

1

禁止だとインタフェースは常にその基本クラスに暗黙的に変換可能であり、常に基本クラスからそれ自身に変換可能である。この動作をオーバーライドするのは冗長で紛らわしく、必要な動作をすべてオーバーライドして正常に動作させることはできないため、許可されません。あなたのケースでは、すべてではなく一部の継承動作をオーバーライドしています。例えば、明示的にキャストするベストプラクティスは次のとおりです。

IEffect anIEffectInstance = GetEffectAsInterface(); 

if(anIEffectInstance is Effect) //<--you cannot override this behavior to return true, 
    var interfaceAscConcrete = (Effect)anIEffectInstance; //<-- so this overridden code would never execute 
0

はジョンスキート等のための質問のように聞こえるが、私はとにかくそれでショットを取りますよ。

あなたが記述した暗黙の演算子は、大部分は不要です。 Effectが既にIEffectを実装している場合は、を使用して、IEffectを実装するオブジェクトが必要な場所であれば、ユーザー定義の変換を気にする必要はありません。

明示的な演算子の問題は、少し哲学的かもしれません。私の理解は、暗黙の変換と明示的な変換のポイントは、あるタイプのオブジェクトを何らかの理由でコンパイラにはまだ明らかでない別のタイプのオブジェクトに変換することです。しかし、インタフェースはオブジェクトではありません。インタフェースを直接インスタンス化することはできません。むしろ、インタフェースはあるクラスによって実装される必要があります。暗黙の変換または明示的な変換を使用すると、結果のオブジェクトは以前のオブジェクトに型によって関連付けられません。つまり、変換の結果として生じるオブジェクトは、独立して立つことができ、実際のオブジェクトタイプを持つことができなければならず、インタフェース自体はそうではありません。

もっと直接的に:暗黙の変換の結果の具体的なタイプはどのようになりますか?コンパイラは知る方法がないため、オブジェクトをインスタンス化することはできません。

このようなことを本当に行う必要がある場合は、インターフェイスを実装する抽象基本クラスを作成するとよいでしょう。その後、オブジェクト型を持つ抽象基本クラスとの間で「変換」することができます。

+0

ありがとうございますが、EffectはIEffectを実装していません。 –

+0

@Joan Vengeあなたは歓迎ですが、効果をIEffectを実装するべきではありませんか?あなたが達成しようとしているものが州のパターンによって役立つでしょうか? (http://en.wikipedia.org/wiki/State_pattern)要約すると、EffectでEffectを実装し、格納されたIEffectのメソッドとプロパティを使用して、EffectクラスでIEffectを実装します。 – Andrew

+0

ありがとう、状態パターンを聞いたことはありませんが、このIEffectはアンマネージAPIへのラッパーです。だから、継承ではなくコンポジションを使用しています。これは、私のAPIのユーザーに実装して公開したくない要素がたくさんあるためです。 –

関連する問題