【问题标题】:Covariant Collection not working协变集合不起作用
【发布时间】:2014-12-12 22:24:18
【问题描述】:

对不起,如果问题是多余的,但我找不到适合我的特殊情况的解决方案。 请考虑这段代码:

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 的不同实现成为可能。 (我不想将gazePoints集合转换为另一种类型的集合,因为它处于一个大循环中,并且我担心性能。

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

【问题讨论】:

  • 您的 AvgPoint 方法没有返回语句。请发布演示实际问题的示例代码...
  • 你能定义doesn't work吗?异常还是错误?
  • 你的方法签名对我来说很好。你是如何实现其余部分的?
  • 谢谢大家,请在@Rufus的回答下找到我的解释。

标签: c# collections covariance


【解决方案1】:

我不确定您遇到的具体问题是什么,但它对我来说是这样的:

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

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

【讨论】:

  • Rufus,非常感谢您的解释并为我编写了整个代码!哇! :-) 请在下面阅读我的回答!
  • Rufus,非常感谢您的解释并为我编写了整个代码!哇! :-) 我的实现和你的完全一样,但有一个不同:我将 GazePoint 定义为 struct,而不是 class,它是问题的根源。现在我的代码有效,但我仍然不知道为什么!如果我将 GazePoint 作为结构并定义一个像“GazePoint gPoint”这样的对象,那么“gPoint is IPoint”为真,“IPoint iPoint = gPoint as IPoint;”工作没有问题,但仍然无法将 'List' 转换为 'IEnumerable'。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 2016-10-03
  • 1970-01-01
  • 2022-01-09
  • 2017-07-22
  • 1970-01-01
相关资源
最近更新 更多