【问题标题】:Is there a polymorphic 2D collection type that includes arrays in c#?c# 中是否存在包含数组的多态 2D 集合类型?
【发布时间】:2019-05-28 23:18:32
【问题描述】:

假设我有一个帮助类,其中包含操作集合的方法:

public static void RemainingDegreeDistribution(IGraph graph, float[,] distArr)
{
    int total = 0;
    for(int i=0; i < graph.Edges.Count; i++)
    {
        int startRemDeg = graph.Edges[i].Start.RemDeg;
        int endRemDeg = graph.Edges[i].End.RemDeg;
        distArr[startRemDeg,endRemDeg]++;
        distArr[endRemDeg, startRemDeg]++;
        total = total+2;
    }

    for(int i=0; i < distArr.GetLength(0); i++)
    {
        for(int j=0; j < distArr.GetLength(1); j++)
        {
            distArr[i,j] /= total;
        }
    }
}

如何更改代码以允许传入的集合为数组或我自己的集合类之一?

麻烦的是,传入的集合必须是二维的。没有一个接口可以在我自己的集合类中实现,数组也实现了。

我希望能够在这两种情况下重用代码,并避免引入大量难看的条件逻辑。我还需要避免分配内存,因此为数组制作某种包装类是不可接受的。我还想避免在列表中使用列表,因为它使用普通的二维数组更简单,并且列表为我的目的分配了太多的内存。使用索引器或其他东西似乎应该可以做到这一点。有没有办法声明“distArr”必须是任何类型,索引器需要两个参数等?

【问题讨论】:

  • KeyValuePair
  • 抱歉,我不太明白这有什么关系。

标签: c# arrays collections interface polymorphism


【解决方案1】:

没有这样的界面。所以你需要自己制作,例如:

public interface IMatrix<T>
{
    int Rows { get; }
    int Columns { get; }
    ref T this[int row, int column] { get; }
}

除了在您的集合类中实现它之外,还可以为数组创建适配器 (Adapter Pattern)。

我知道,我知道,你说

我还需要避免分配内存,因此为数组创建某种包装类是不可接受的。

我不认为一个短暂的 GC3 生成包装器对象会损害您的系统,但无论如何,可以通过将包装器实现为 struct 来避免堆分配:

public struct ArrayMatrix<T> : IMatrix<T>
{
    readonly T[,] source;
    public ArrayMatrix(T[,] source) => this.source = source;
    public int Rows => source.GetLength(0);
    public int Columns => source.GetLength(1);
    public ref T this[int row, int column] => ref source[row, column];
}

并使您的方法通用(以避免struct 的装箱):

public static void RemainingDegreeDistribution<TMatrix>(IGraph graph, TMatrix distArr)
    where TMatrix : IMatrix<float>
{
    int total = 0;
    for (int i = 0; i < graph.Edges.Count; i++)
    {
        int startRemDeg = graph.Edges[i].Start.RemDeg;
        int endRemDeg = graph.Edges[i].End.RemDeg;
        distArr[startRemDeg, endRemDeg]++;
        distArr[endRemDeg, startRemDeg]++;
        total = total + 2;
    }

    for (int i = 0; i < distArr.Rows; i++)
    {
        for (int j = 0; j < distArr.Columns; j++)
        {
            distArr[i, j] /= total;
        }
    }
}

为了更容易与数组一起使用,您可以添加一个辅助方法:

public static class ArrayMatrix
{
    public static ArrayMatrix<T> ToMatrix<T>(this T[,] source) => new ArrayMatrix<T>(source);
}

甚至为你的方法提供数组参数的重载:

public static void RemainingDegreeDistribution(IGraph graph, float[,] distArr)
    => RemainingDegreeDistribution(graph, distArr.ToMatrix());

【讨论】:

    【解决方案2】:

    如果您需要在 2D 空间中表示点,我建议您使用点数据结构。 https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2

    如果你还要传递一个坐标和点数组,请尝试重载:

    public static Method ( float[,] coordinates )
    {
         //generate array of Points starting from coordinates , points.Add ( new Point(coordinate[i,j]) )
    }
    
    public static Method ( Point[] points)
    {
         //actual logic
    }
    

    【讨论】:

      猜你喜欢
      • 2016-05-20
      • 1970-01-01
      • 1970-01-01
      • 2013-04-20
      • 2015-01-04
      • 2011-11-21
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多