Is there a polymorphic 2D collection type that includes arrays in c#?












0















So let's say I have a helper class which contains methods that manipulate a collection:



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


How can I change the code to allow the collection that is passed in to either be an array or one of my own collection classes?



The trouble is, the collection that is passed in must be 2-dimensional. There isn't an interface that I can implement in my own collection classes that arrays also implement.



I want to be able to reuse the code for both cases and avoid introducing lots of ugly conditional logic. I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable. I also want to avoid using lists within lists as its so much simpler to work with normal 2d arrays and lists allocate too much memory for my purposes. It seems like this should be possible with indexers or something. Like is there a way to declare that "distArr" must be any type with an indexer that takes two arguments etc.?










share|improve this question

























  • KeyValuePair<string, object[,]>

    – jdweng
    Jan 2 at 9:54






  • 1





    Sorry I don't quite understand how that is related.

    – Jonathan
    Jan 2 at 19:35
















0















So let's say I have a helper class which contains methods that manipulate a collection:



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


How can I change the code to allow the collection that is passed in to either be an array or one of my own collection classes?



The trouble is, the collection that is passed in must be 2-dimensional. There isn't an interface that I can implement in my own collection classes that arrays also implement.



I want to be able to reuse the code for both cases and avoid introducing lots of ugly conditional logic. I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable. I also want to avoid using lists within lists as its so much simpler to work with normal 2d arrays and lists allocate too much memory for my purposes. It seems like this should be possible with indexers or something. Like is there a way to declare that "distArr" must be any type with an indexer that takes two arguments etc.?










share|improve this question

























  • KeyValuePair<string, object[,]>

    – jdweng
    Jan 2 at 9:54






  • 1





    Sorry I don't quite understand how that is related.

    – Jonathan
    Jan 2 at 19:35














0












0








0








So let's say I have a helper class which contains methods that manipulate a collection:



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


How can I change the code to allow the collection that is passed in to either be an array or one of my own collection classes?



The trouble is, the collection that is passed in must be 2-dimensional. There isn't an interface that I can implement in my own collection classes that arrays also implement.



I want to be able to reuse the code for both cases and avoid introducing lots of ugly conditional logic. I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable. I also want to avoid using lists within lists as its so much simpler to work with normal 2d arrays and lists allocate too much memory for my purposes. It seems like this should be possible with indexers or something. Like is there a way to declare that "distArr" must be any type with an indexer that takes two arguments etc.?










share|improve this question
















So let's say I have a helper class which contains methods that manipulate a collection:



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


How can I change the code to allow the collection that is passed in to either be an array or one of my own collection classes?



The trouble is, the collection that is passed in must be 2-dimensional. There isn't an interface that I can implement in my own collection classes that arrays also implement.



I want to be able to reuse the code for both cases and avoid introducing lots of ugly conditional logic. I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable. I also want to avoid using lists within lists as its so much simpler to work with normal 2d arrays and lists allocate too much memory for my purposes. It seems like this should be possible with indexers or something. Like is there a way to declare that "distArr" must be any type with an indexer that takes two arguments etc.?







c# arrays collections interface polymorphism






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 2 at 19:34







Jonathan

















asked Jan 2 at 9:46









JonathanJonathan

5343715




5343715













  • KeyValuePair<string, object[,]>

    – jdweng
    Jan 2 at 9:54






  • 1





    Sorry I don't quite understand how that is related.

    – Jonathan
    Jan 2 at 19:35



















  • KeyValuePair<string, object[,]>

    – jdweng
    Jan 2 at 9:54






  • 1





    Sorry I don't quite understand how that is related.

    – Jonathan
    Jan 2 at 19:35

















KeyValuePair<string, object[,]>

– jdweng
Jan 2 at 9:54





KeyValuePair<string, object[,]>

– jdweng
Jan 2 at 9:54




1




1





Sorry I don't quite understand how that is related.

– Jonathan
Jan 2 at 19:35





Sorry I don't quite understand how that is related.

– Jonathan
Jan 2 at 19:35












2 Answers
2






active

oldest

votes


















2














There is no such interface. So you need to make your own, for instance:



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


and additionally of implementing it in your collection classes, create adapter for arrays (Adapter Pattern).



I know, I know, you said




I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable.




I don't think a tiny short lived GC3 generation wrapper object will hurt your system, but anyway, the heap allocation can be avoided by implementing the wrapper as a 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];
}


and making your method generic (to avoid boxing of the 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;
}
}
}


To make it easier to be used with arrays, you could add a helper method:



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


and even provide overload of your method with array argument:



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





share|improve this answer































    0














    If you need to represent point in 2D space i suggesto you to use Point data structure.
    https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2



    Try overloading if you also would pass an array of coordinates and points :



    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
    }





    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004138%2fis-there-a-polymorphic-2d-collection-type-that-includes-arrays-in-c%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      There is no such interface. So you need to make your own, for instance:



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


      and additionally of implementing it in your collection classes, create adapter for arrays (Adapter Pattern).



      I know, I know, you said




      I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable.




      I don't think a tiny short lived GC3 generation wrapper object will hurt your system, but anyway, the heap allocation can be avoided by implementing the wrapper as a 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];
      }


      and making your method generic (to avoid boxing of the 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;
      }
      }
      }


      To make it easier to be used with arrays, you could add a helper method:



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


      and even provide overload of your method with array argument:



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





      share|improve this answer




























        2














        There is no such interface. So you need to make your own, for instance:



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


        and additionally of implementing it in your collection classes, create adapter for arrays (Adapter Pattern).



        I know, I know, you said




        I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable.




        I don't think a tiny short lived GC3 generation wrapper object will hurt your system, but anyway, the heap allocation can be avoided by implementing the wrapper as a 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];
        }


        and making your method generic (to avoid boxing of the 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;
        }
        }
        }


        To make it easier to be used with arrays, you could add a helper method:



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


        and even provide overload of your method with array argument:



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





        share|improve this answer


























          2












          2








          2







          There is no such interface. So you need to make your own, for instance:



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


          and additionally of implementing it in your collection classes, create adapter for arrays (Adapter Pattern).



          I know, I know, you said




          I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable.




          I don't think a tiny short lived GC3 generation wrapper object will hurt your system, but anyway, the heap allocation can be avoided by implementing the wrapper as a 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];
          }


          and making your method generic (to avoid boxing of the 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;
          }
          }
          }


          To make it easier to be used with arrays, you could add a helper method:



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


          and even provide overload of your method with array argument:



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





          share|improve this answer













          There is no such interface. So you need to make your own, for instance:



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


          and additionally of implementing it in your collection classes, create adapter for arrays (Adapter Pattern).



          I know, I know, you said




          I also need to avoid allocating memory so making some kind of wrapper class for arrays isn't acceptable.




          I don't think a tiny short lived GC3 generation wrapper object will hurt your system, but anyway, the heap allocation can be avoided by implementing the wrapper as a 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];
          }


          and making your method generic (to avoid boxing of the 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;
          }
          }
          }


          To make it easier to be used with arrays, you could add a helper method:



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


          and even provide overload of your method with array argument:



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






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 3 at 23:40









          Ivan StoevIvan Stoev

          108k788142




          108k788142

























              0














              If you need to represent point in 2D space i suggesto you to use Point data structure.
              https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2



              Try overloading if you also would pass an array of coordinates and points :



              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
              }





              share|improve this answer




























                0














                If you need to represent point in 2D space i suggesto you to use Point data structure.
                https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2



                Try overloading if you also would pass an array of coordinates and points :



                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
                }





                share|improve this answer


























                  0












                  0








                  0







                  If you need to represent point in 2D space i suggesto you to use Point data structure.
                  https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2



                  Try overloading if you also would pass an array of coordinates and points :



                  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
                  }





                  share|improve this answer













                  If you need to represent point in 2D space i suggesto you to use Point data structure.
                  https://docs.microsoft.com/en-us/dotnet/api/system.drawing.point?view=netframework-4.7.2



                  Try overloading if you also would pass an array of coordinates and points :



                  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
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 2 at 10:29









                  SkarySkary

                  618726




                  618726






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54004138%2fis-there-a-polymorphic-2d-collection-type-that-includes-arrays-in-c%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Can a sorcerer learn a 5th-level spell early by creating spell slots using the Font of Magic feature?

                      Does disintegrating a polymorphed enemy still kill it after the 2018 errata?

                      A Topological Invariant for $pi_3(U(n))$