2011-11-08 5 views
3

C#でオブジェクトをキャストして、インターフェイスで宣言されているオブジェクトメソッド以外のオブジェクトメソッドを使用できるという問題があります。以下は、私が話していることの簡単な例です。すべてのオブジェクト機能を使用できるようにC#でインターフェイスをキャストする

public interface IShape 
{ 
    void Print(); 
} 

public class Square : IShape 
{ 
    #region IShape Members 

    public void Print() 
    { 
     HttpContext.Current.Response.Write("Square Print Called"); 
    } 

    #endregion 

    public void PrintMore() 
    { 
     HttpContext.Current.Response.Write("Square Print More Called"); 
    }   
} 

なぜこのコードが呼び出されると、PrintMore()にアクセスできないのですか?

IShape s = (Square)shape; 
s.PrintMore() // This is not available. only Print() is. 

助けと説明が役に立ちますか?このコードs

+1

オブジェクトが「正方形」ではなく、「正方形」ではないためです。キャストの「問題」です。それは完全に正常です:) – ykatchou

+0

あなたのエンドリージョンが間違った場所にあります。それはちょっと混乱します。 – CodesInChaos

+0

@CodeInChaos:そうは思わない。インターフェイスにはメソッドが1つしかなく、そのメソッドはその領域内にあります。非インターフェイスメソッドは、その外にあります。 – Chris

答えて

5

あなたs変数の型IShapeのままです。コンパイラが関連する限り、型を変更しても型を変更しないときにキャストを使用したためです。あなたが必要があると思います。もちろん

Square s = (Square) shape; 
s.PrintMore(); 

shapeが本当には、(起こってカスタム変換が存在しないと仮定した場合)Squareであれば、これはのみ動作します。

私は、あなたがこのルートを下る前に慎重に考えることをお勧めします。通常、このようなキャストは幾分抽象化を破っていることを示しています。IShapeとしてshapeを知っているだけの場合はになります。(通常は)IShapeのメンバーで必要なことを行うことができます。それはケースがない場合は、次のことができます。

  • ではなく IShape
  • キャストのSquareを受け入れるようにコードを変更し
  • IShapeより強力な(それを与えるより多くのメンバーを)作る絶対に必要であれば
+0

優れた設計上のポイント... –

+0

ポイントありがとうございます。私は正しいアプローチを取ることとその背後にある推論を完全に理解している点に着手しようとしています。ときには解決策が素晴らしいこともありますが、理由を理解できない場合は解決できません。 – Dietpixel

2
IShape s = (Square)shape; 
s.PrintMore(); 

はまだIShape、ないSquareです。変数は、宣言で定義した型を保持します。コードを動作するように

は次のようになります。

そんなにIShapeにのみメソッドが用意されていIShapeですよコンパイラを言っている IShape s = (Square)shape;ラインで
Square s = (Square)shape; 
s.PrintMore(); 
+0

これは本当に彼の質問に答えません - なぜですか? –

+0

@JoelEtherton:いくつかの説明を追加しました。 – Matthieu

3

あなたのユーザーの場合:

Square s = (Square)shape; 
s.PrintMore() 

次にあなたが欲しいものを行う必要があります。

ここで重要なことは、変数を宣言するときにコンパイラに何を伝えているのかというと、そのオブジェクトにどのオブジェクトを入れても問題にならないということです。

4

IShape参照のPrintMore()にアクセスしようとしています。IShapeの参照は、彼らが宣言するPrint()メソッドを参照してください。

(Square) shapeのキャストはすぐにIShapeの参照に格納されているので、何もしていません。あなたがもしわからない場合は、

Square s = (Square) shape; 
s.PrintMore(); 

それとも

IShape s = shape; 
((Square)s).PrintMore(); 

または:次のいずれかの鋳造によってSquareとなる基準自体を必要とSquare参照中、または呼び出しの前にキャストして、それを保存しますそれはasキャストを使用し、Squareかではありません。

Square s = shape as Square; 

// will cast if it is a Square, otherwise, returns null 
// this doesn't work for value types (int, struct, etc) 
if (s != null) 
{ 
    s.PrintMore(); 
} 
+0

コメントありがとうございます。 – Dietpixel

1

あなたがアクセスすることができない理由PrintMoreメソッドは、タイプキャストされたシェイプをIShapeとして定義された変数に再割り当てするためです。それが良い見てみる価値があるかもしれないが、

((Square) shape).PrintMore(); 

Square s = (Square)shape; 
s.PrintMore(); 

または代わりに:あなたは例えばタイプSquareの変数に格納する必要がSquareクラスのメソッドを使用できるようにするにはあなたのコードでは、これらの型キャストは通常​​、おそらくそれが理想的ではないという良い警告兆候です。おそらくIShapeにはPrintMoreの方法が必要ですか、今のところSquareのオブジェクトのみを受け入れるべきですか?少なくとも私はshapeがこのタイプのキャストを行う前に実際にタイプSquareであることを確認することを提案します。例えば

Square s = shape as Square; 

if (s != null) 
    s.PrintMore(); 
1

しようとすると、s.PrintMore() "s"はタイプがIShapeなので、インターフェイス機能についてしか知りません。あなただけのインターフェイスで定義された関数のみを公開し、あなたのオブジェクトのラッパーのようなインターフェースのだと思い

((Square)shape).PrintMore(); // assuming you're positive its a Square type 
Square s = (Square)shape; 
s.PrintMore(); 

または

ような何かをする必要があると思います。彼らはまだそこにいる、あなたはちょうど適切なオブジェクトにキャストなしでアクセスすることはできません。

関連する問題