Transmitir en C # con interfaces para poder usar todas las funciones de los objetos

I'm having a bit of an issue casting my objects in C# to be able to use the additional object methods besides the ones declared in the interface. Below is a simple example of what I am speaking about.

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"); 
    }        
}

Why when this code below is called am I not able to access PrintMore()?

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

Any help and explanation would be helpful?

preguntado el 08 de noviembre de 11 a las 15:11

Because your object is an "IShape" and not a "Square". It's a cast "issue". It's totally normal :) -

Your endregion is in the wrong place. That's a bit confusing. -

@CodeInChaos: I don't think it is. There is only one method on the interface and that is inside the region. The non-interface method is outside of it... -

@Chris check the edit history. It was, at the time of the comment. -

@CodeInChaos: Ah, my apologies. I usually try to be good about that but obviously missed it this time. :) -

6 Respuestas

Sus s variable is still of type IShape. Just because you happen to have used a cast when assigning to it doesn't change the type as far as the compiler's concerned. You'd need:

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

Of course, this will only work if shape realmente is a Square (assuming there aren't custom conversions going on).

I would advise you to think carefully before going down this route though. Usually a cast like this indicates that you're breaking abstraction somewhat - if you only know about shape como una IShape, Que debemos (usually) be able to do what you need just with the members of IShape. If that's not the case, you can:

  • Realice IShape more powerful (give it more members)
  • Change your code to accept a Square en lugar de un IShape
  • Cast if absolutely necessary

respondido 08 nov., 11:19

Thanks for the points. I'm attempting to get to the point that I fully understand the correct approach to take and the reasoning behind it. Sometimes the solution is great, but if you never understand why, it does not help. - Dietpixel

The problem is you are trying to access PrintMore() off of an IShape referencia, IShape references only see the Print() method they declare.

So the cast you have (Square) shape is doing nothing because it is immediately storing it into an IShape reference. You need the reference itself to be Square by either casting and storing it in a Square reference, or by casting before the invoke:

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

Or

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

Or, if you aren't sure if it's a Square or not, use an as emitir:

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();
}

respondido 08 nov., 11:19

En la linea IShape s = (Square)shape; you are telling the compiler that s is an IShape so only methods on IShape are available.

If you user:

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

Then that should do what you want.

The key point here is that when you declare a variable you tell the compiler what it is and it doesn't then matter what object you put into that.

respondido 08 nov., 11:19

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

Con este código s sigue siendo un IShapeno es un Square. A variable keeps the type you have defined at his declaration, whatever you try to fill in it.

To work the code should be :

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

respondido 08 nov., 11:19

This doesn't really answer his question -- why? - Joel Etherton

@JoelEtherton : added some explanations. - Mateo

The reason you are unable to access the PrintMore method is because you're reassigning the type-casted shape, back to a variable defined as IShape. To be able to use methods on the Square class you need to store it in a variable of type Square por ejemplo:

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

o alternativamente:

((Square) shape).PrintMore();

Although it might be worth taking a good look at your code, type-casts such as these are usually a good warning sign that perhaps it is not ideal. Perhaps IShape debería tener el PrintMore method, or perhaps you should only be accepting Square objects at this point? At the very least I'd suggest making sure that the shape es en realidad de tipo Square before doing this type cast.

Por ejemplo:

Square s = shape as Square;

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

respondido 08 nov., 11:19

Because when you try s.PrintMore() "s" is of type IShape, so it only knows about the interface functions. You'd need to do something like

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

or

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

Think of the interface like a wrapper over your object that only exposes only the functions defined in the interface. They're still there, you just can't access them without a cast to the appropriate object.

respondido 08 nov., 11:19

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.