接口如何逐步实现更严格的类型属性?

时间:2011-04-27 06:34:51

标签: c# .net inheritance interface

我正在研究一系列数据结构。有些需要特定数量的维度(如四叉树或八叉树),有些则允许任何数量(例如kd-trees)。我想实现我的不同结构和接口如下:

public struct Point : IPoint // An n-dimensional point
public struct Point2D : IPoint // A 2-dimensional point

public interface IPointEntity
{
    IPoint Location { get; }
}
public interface IPointEntity2D : IPointEntity
{
    Point2D Location { get; }
}

这样,我可以创建这样的类:

public class Quadtree
{
    public void Add(IPointEntity2D value) {...}
}

public class KdTree
{
    public void Add(IPointEntity value) {...}
}

但是,我被告知IPointEntity2D必须将Location声明为New,因为它隐藏IPointEntity.Location。然而,这违背了目的,因为我必须单独实施它们。在我看来,2D实现应该满足n-D接口的要求。我怎么能做到这一点?


修改 我现在按照Jon Skeet的建议实现了它:

public struct Point : IPoint // An n-dimensional point
public struct Point2D : IPoint // A 2-dimensional point

public interface IPointEntity<T> where T : IPoint
{
    T Location { get; }
}

public class Quadtree<T> where T : IPointEntity<Point2D>
{
    public void Add(T value) {...}
}

public class KdTree<T> where T : IPointEntity<IPoint>
{
    public void Add(T value) {...}
}

但是当我尝试创建一个实体时,我不能像我希望的那样在两个合适的类中使用它们:

public class Sprite2D : IPointEntity<Point2D>
{
    public Point2D Location { get; set; }
}
public class Sprite3D : IPointEntity<Point3D>
{
    public Point3D Location { get; set; }
}

static void Main(string[] args)
{
    var quadtree = new Quadtree<Sprite2D>(); // Works just great
    var kdTree2D = new KdTree<Sprite2D>();   // Doesn't work
    var kdTree3D = new KdTree<Sprite3D>();   // Doesn't work
}

2 个答案:

答案 0 :(得分:4)

您正在寻找协变返回类型 - 它们在.NET中不存在。您必须使用显式接口实现单独实现这两个属性,以避免它们发生冲突。

一种可能的解决方法是使用通用接口:

public interface IPointEntity<T> where T : IPoint
{
    T Location { get; }
}

请注意,允许类实现IPointEntity<Point>并避免在访问Point时将IPoint装入。{/ p>

答案 1 :(得分:1)

您可以使用通用界面

public interface IPointEntity<T> where T : IPoint 
{
    T Location { get; }
}

IPointEntity2D继承IPointEntity<Point2D>