Skip to main content
Code Review

Return to Question

replaced http://stackoverflow.com/ with https://stackoverflow.com/
Source Link

Knowing that C# is optimized for single-dimensional arrays optimized for single-dimensional arrays, I decided to make a simple wrapper class that contains an internal jagged array, but have it look and behave like a 2-dimensional array.

Knowing that C# is optimized for single-dimensional arrays, I decided to make a simple wrapper class that contains an internal jagged array, but have it look and behave like a 2-dimensional array.

Knowing that C# is optimized for single-dimensional arrays, I decided to make a simple wrapper class that contains an internal jagged array, but have it look and behave like a 2-dimensional array.

deleted 16 characters in body; edited title
Source Link
Jamal
  • 35.2k
  • 13
  • 134
  • 238

When should I actually derive from my interface? Interface for a transformable grid

Context:

I am working on an XNAXNA project, and since procedural generation is likely to be used, I wanted to eventually create a helper class to work with data to facilitate that.

  • Attach it to IGrid<T>. It's no longer about simply storing the data, but transforming it as well.
  • Attach it to Grid<T>. The fact that a grid can transform the data is an implementation detail.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.
  • Create a derived class Mesh<T>, but remove ITransformableITransformable<T> and move its methods into this class.

Since generic types do not support operator overloading (+, -, /, *), it means that if I want a HeightmapHeightmap to support addition in the form of Heightmap m = a + b, it would need a specific implementation, such as public class Heightmap : Mesh<float>, which then supplies the implementation of the operators.

When should I actually derive from my interface?

Context:

I am working on an XNA project, and since procedural generation is likely to be used, I wanted to eventually create a helper class to work with data to facilitate that.

  • Attach it to IGrid<T>. It's no longer about simply storing the data, but transforming it as well.
  • Attach it to Grid<T>. The fact that a grid can transform the data is an implementation detail.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.
  • Create a derived class Mesh<T>, but remove ITransformable and move its methods into this class.

Since generic types do not support operator overloading (+, -, /, *), it means that if I want a Heightmap to support addition in the form of Heightmap m = a + b, it would need a specific implementation, such as public class Heightmap : Mesh<float>, which then supplies the implementation of the operators.

Interface for a transformable grid

I am working on an XNA project, and since procedural generation is likely to be used, I wanted to eventually create a helper class to work with data to facilitate that.

  • Attach it to IGrid<T>. It's no longer about simply storing the data, but transforming it as well.
  • Attach it to Grid<T>. The fact that a grid can transform the data is an implementation detail.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.
  • Create a derived class Mesh<T>, but remove ITransformable<T> and move its methods into this class.

Since generic types do not support operator overloading (+, -, /, *), it means that if I want a Heightmap to support addition in the form of Heightmap m = a + b, it would need a specific implementation, such as public class Heightmap : Mesh<float>, which then supplies the implementation of the operators.

Added a lot more detail
Source Link
Kyle Baran
  • 411
  • 4
  • 9

Context:

I am working on an XNA project, and since procedural generation is likely to be used, I wanted to eventually create a helper class to work with data to facilitate that.

Design Goal:

Originally, I wanted to generate and modify a heightmap in a simple but efficient manner. The most straightforward approach to handle this would be a with a float[,].

Right now, I have a Grid<T> which simply holds the data in a more convenient manner, but I want to introduce a way to transform it somehow - slicing, rotations, etc. The ability to add and multiply different heightmaps together would be beneficial as well.

My Code:

Knowing that C# is optimized for single-dimensional arrays, I decided to make a simple wrapper class that acts like acontains an internal jagged array under the hood, but have it look and behave like a 2-dimensional array.

I first made it into an interface because doing so allows me to implement it however I want, allowingwhich allows for future optimizations thatwhich won't break clientany dependent code:

// Presents itself as a simplified 2-dimensional array
public interface IGrid<T> : IEnumerable<T>, IEnumerable
{
 Point Size { get; }
 T this[int x, int y] { get; set; }
}
// Functions as a jagged array under the hood
public class Grid<T> : IGrid<T>
{
 private readonly T[][] _values;
 // SatisfyImplement IGrid<T>
 public Point Size { get; private set; }
 public T this[int x, int y]
 {
 get { return _values[y][x]; }
 set { _values[y][x] = value; }
 }
 // Constructor
 public Grid(int x, int y)
 {
 Size = new Point(x, y);
 _values = new T[y][];
 for (int i = 0; i < y; i++)
 _values[i] = new T[x];
 }
 
 // Provide IEnumerator, override ToString(), etc...
}

My primary use for this class would likely be to create a heightmap, usableapproach for terrain generation, etc. To facilitate that, I thought it would be prudent to support different operations, such as rotating and slicing the datatransformation bits is similar:

But... after I made that interface,And here is where I had no ideaam stumbling. I'm not actually sure what to with it! I had no idea where it made the most sensewant to attachdo with it.!

  • UseAttach it withto IGrid<T>. It's no longer about simply holdingstoring the data, but also transforming it as well.
  • UseAttach it withto Grid<T>. The fact that ita grid can now transform the data is an implementation detail.
  • Create an extension method for any 2-dimensional arrays (defeating the purpose of IGrid<T>), or create an extension method for IGrid<T> itself.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.
  • Create a derived class Mesh<T>, but remove ITransformable and move its methods into this class.

Thoughts:

Since generic types do not support operator overloading (+, -, /, *), it means that if I want a Heightmap to support addition in the form of Heightmap m = a + b, it would need a specific implementation, such as public class Heightmap : Mesh<float>, which then supplies the implementation of the operators.

Based on that, my entire class chain might resemeble:

public interface IGrid<T> { ... }
public interface IMesh<T> : IGrid<T> { ... }
public class Grid<T> : IGrid<T> { ... }
public class Mesh<T> : Grid<T>, IMesh<T> { ... }
public class Heightmap : Mesh<float> { ... }

Knowing that C# is optimized for single-dimensional arrays, I decided to make a simple wrapper class that acts like a jagged array under the hood, but look like a 2-dimensional array.

I made it into an interface because doing so allows me to implement it however I want, allowing for future optimizations that won't break client code:

public interface IGrid<T> : IEnumerable<T>, IEnumerable
{
 Point Size { get; }
 T this[int x, int y] { get; set; }
}
public class Grid<T> : IGrid<T>
{
 private readonly T[][] _values;
 // Satisfy IGrid<T>
 public Point Size { get; private set; }
 public T this[int x, int y]
 {
 get { return _values[y][x]; }
 set { _values[y][x] = value; }
 }
 // Constructor
 public Grid(int x, int y)
 {
 Size = new Point(x, y);
 _values = new T[y][];
 for (int i = 0; i < y; i++)
 _values[i] = new T[x];
 }
 
 // Provide IEnumerator, override ToString(), etc...
}

My primary use for this class would likely be to create a heightmap, usable for terrain generation, etc. To facilitate that, I thought it would be prudent to support different operations, such as rotating and slicing the data:

But... after I made that interface, I had no idea what to with it! I had no idea where it made the most sense to attach it.

  • Use it with IGrid<T>. It's no longer about simply holding data, but also transforming it.
  • Use it with Grid<T>. The fact that it can now transform the data is an implementation detail.
  • Create an extension method for any 2-dimensional arrays (defeating the purpose of IGrid<T>), or create an extension method for IGrid<T> itself.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.

Context:

I am working on an XNA project, and since procedural generation is likely to be used, I wanted to eventually create a helper class to work with data to facilitate that.

Design Goal:

Originally, I wanted to generate and modify a heightmap in a simple but efficient manner. The most straightforward approach to handle this would be a with a float[,].

Right now, I have a Grid<T> which simply holds the data in a more convenient manner, but I want to introduce a way to transform it somehow - slicing, rotations, etc. The ability to add and multiply different heightmaps together would be beneficial as well.

My Code:

Knowing that C# is optimized for single-dimensional arrays, I decided to make a simple wrapper class that contains an internal jagged array, but have it look and behave like a 2-dimensional array.

I first made it into an interface because doing so allows me to implement it however I want, which allows for future optimizations which won't break any dependent code:

// Presents itself as a simplified 2-dimensional array
public interface IGrid<T> : IEnumerable<T>, IEnumerable
{
 Point Size { get; }
 T this[int x, int y] { get; set; }
}
// Functions as a jagged array under the hood
public class Grid<T> : IGrid<T>
{
 private readonly T[][] _values;
 // Implement IGrid<T>
 public Point Size { get; private set; }
 public T this[int x, int y]
 {
 get { return _values[y][x]; }
 set { _values[y][x] = value; }
 }
 // Constructor
 public Grid(int x, int y)
 {
 Size = new Point(x, y);
 _values = new T[y][];
 for (int i = 0; i < y; i++)
 _values[i] = new T[x];
 }
 
 // Provide IEnumerator, override ToString(), etc...
}

My approach for the transformation bits is similar:

And here is where I am stumbling. I'm not actually sure what I want to do with it!

  • Attach it to IGrid<T>. It's no longer about simply storing the data, but transforming it as well.
  • Attach it to Grid<T>. The fact that a grid can transform the data is an implementation detail.
  • Create a derived class Mesh<T> which does everything Grid<T> does, but also implements ITransformable<T>.
  • Create a derived class Mesh<T>, but remove ITransformable and move its methods into this class.

Thoughts:

Since generic types do not support operator overloading (+, -, /, *), it means that if I want a Heightmap to support addition in the form of Heightmap m = a + b, it would need a specific implementation, such as public class Heightmap : Mesh<float>, which then supplies the implementation of the operators.

Based on that, my entire class chain might resemeble:

public interface IGrid<T> { ... }
public interface IMesh<T> : IGrid<T> { ... }
public class Grid<T> : IGrid<T> { ... }
public class Mesh<T> : Grid<T>, IMesh<T> { ... }
public class Heightmap : Mesh<float> { ... }
Source Link
Kyle Baran
  • 411
  • 4
  • 9
Loading
lang-cs

AltStyle によって変換されたページ (->オリジナル) /