简体   繁体   中英

Different types in C# Interface Implementation

I really struggle entitling this, but i'll try my best at explaining my point.

Say i have this :

    List<IShape> Shapes = new List<IShape>();

    public interface IShape {
       dynamic shapeAttributes { get; set; }
    };

    public struct SquareAttributes {
      float sizeOfSide;
    };

    public struct CircleAttributes {
      float radius
    };
    
    public class Square : IShape {
      SquareAttributes shapeAttributes { get; set; }
    };

    public class Circle : IShape {
      CircleAttributes shapeAttributes { get; set; }
    };

    Shapes.Add(new Square());
    Shapes.Add(new Circle());
    

How Do I make that situation work ? Here the "dynamic" keyword in IShape is not resolved when implemented in Square and Circle, but I'd still want to be able to define the right Type when implementing rather than using "dynamic" everywhere. Is there a right way to deal with this, with the ability re regroup all kind of Shapes in the same list? I hope this is clear.

I obviously simplified the whole thing to get straight to the point, but everything involved is far more complex and cannot really be fitted into a single large piece.

If your shapes attributes very different you can use System.Object as common type. But don't forget to check if you pass correct ShapeAttributes type to correct implementation of IShape , so I recommend to use set method instead of property setter:

Objects definition:


public interface IShape
{
    object ShapeAttributes { get;  }
    Type ShapeAttributesType { get; }
    void SetAttributes(object shapeAttributes);
}

public class Square : IShape
{
    public object ShapeAttributes { get; private set; }
    public Type ShapeAttributesType => typeof(SquareAttributes);     
    public void SetAttributes(object shapeAttributes)
    {
        // Check if passed correct type
        if (shapeAttributes.GetType() != ShapeAttributesType)
            throw new ArgumentException($"Argument type must be {ShapeAttributesType.FullName}", nameof(shapeAttributes));
        ShapeAttributes = shapeAttributes;
    }
}

public class Circle : IShape
{
    public object ShapeAttributes { get; private set; }
    public Type ShapeAttributesType => typeof(CircleAttributes);        
    public void SetAttributes(object shapeAttributes)
    {
        // Check if passed correct type
        if (shapeAttributes.GetType() != ShapeAttributesType)
            throw new ArgumentException($"Argument type must be {ShapeAttributesType.FullName}", nameof(shapeAttributes));
        ShapeAttributes = shapeAttributes;
    }
}

public struct SquareAttributes
{
    public float SizeOfSide { get; set; }
}

public struct CircleAttributes
{
    public float Radius { get; set; }
}

Usage example:


List<IShape> shapes = new List<IShape>();
var square = new Square();
square.SetAttributes(new SquareAttributes()
{
    SizeOfSide = 4.1f
});

var circle = new Circle();
circle.SetAttributes(new CircleAttributes()
{
    Radius = 2.12f
});

shapes.Add(square);
shapes.Add(circle);

foreach (var shape in shapes)
{
    //Cast ShapeAttributes based on owner class type
    switch (shape)
    {
        case Square s:
            var size = ((SquareAttributes)s.ShapeAttributes).SizeOfSide;
            Console.WriteLine($"Square.ShapeAttributes.SizeOfSide = {size}");
            break;
        case Circle c:
            var radius = ((CircleAttributes)c.ShapeAttributes).Radius;
            Console.WriteLine($"Circle.ShapeAttributes.Radius = {radius}");
            break;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM