协变集合不起作用

本文关键字:不起作用 集合 | 更新日期: 2023-09-27 18:34:13

抱歉,如果这个问题是多余的,但我找不到适合我的特定情况的解决方案。请考虑以下代码块:

public interface IPoint {}
public class GazePoint : IPoint {}
public Point AvgPoint(IEnumerable<IPoint> locations) {}
List<GazePoint> gazePoints = new List<GazePoint>();
//...
// this doesn't work:
Point avg = AvgPoint(gazePoints);

您能否解释一下为什么它不起作用(我假设 C# 4.0 已经解决了这个问题)以及如何更改 AvgPoint() 方法的签名以接收 IPoint 的不同实现。(我不想把凝视点收藏投到另一种类型的收藏上,因为它处于一个大循环中,我担心性能。

[更新]:我将GazePoint定义为结构,这是问题的根源。不过,我不知道为什么结构在这里不起作用。

协变集合不起作用

我不确定您遇到的确切问题是什么,但以下是它对我的工作方式:

首先,一些实际的类实现:

public interface IPoint
{
    int X { get; set; }
    int Y { get; set; }
}
public class Point : IPoint
{
    public int X { get; set; }
    public int Y { get; set; }
    public Point()
    {
    }
    public Point(int x, int y)
    {
        X = x;
        Y = y;
    }
}
public class GazePoint : IPoint
{
    public int X { get; set; }
    public int Y { get; set; }
    public GazePoint()
    {
    }
    public GazePoint(int x, int y)
    {
        X = x;
        Y = y;
    }
}

然后是一个实际的 AvgPoint 方法实现:

public static Point AvgPoint(IEnumerable<IPoint> locations)
{
    if (locations == null || !locations.Any()) return new Point(0, 0);
    return new Point((int) locations.Average(l => l.X), 
        (int) locations.Average(l => l.Y));
}

最后是一些测试:

public static void Main()
{
    var points = new List<Point>
    {
        new Point(1, 2),
        new Point(3, 4)
    };
    var gazePoints = new List<GazePoint>
    {
        new GazePoint(1, 2),
        new GazePoint(3, 4)
    };
    Point avgPoint = AvgPoint(points);
    Point avgGazePoint = AvgPoint(gazePoints);
    Console.WriteLine("Average Point = {0}, {1}", avgPoint.X, avgPoint.Y);
    Console.WriteLine("Average GazePoint = {0}, {1}", avgGazePoint.X, avgGazePoint.Y);
}

如果您的目标是让该方法返回传入的相同类型的平均值,则可以使其泛型,如下所示:

public static T AvgPoint<T>(IEnumerable<T> locations) where T : IPoint, new()
{
    if (locations == null || !locations.Any()) return new T {X = 0, Y = 0};
    return new T {X = (int) locations.Average(l => l.X), 
        Y = (int) locations.Average(l => l.Y)};
}