Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are some examples of dynamic/generic/other methods for generating return type based on caller's type?

In the context of C#, .Net 4...

Given a data source object that supplies vertices by index from an array of doubles where a vertex contains ten doubles with members Px, Py, Pz, Nx, Ny, Nz, S, T, U, V. and the backing array contains all or any subset of vertex members based on the data source's stride, offset and count properties. The data source could be simplified as:

  public class DataSource
  {
    private double[] data;
    private int offset, stride, count;

    public double[] ElementAt(int index)
    {
      double[] result = new double[count];
      var relativeIndex =  index * stride + offset;
      Array.Copy(data, relativeIndex, result, 0, count);
      return result;
    }
    .
    .
    .
  }

Some consumers would be interested in a return type of double[], but most would request data as a PointNf type where N is the number of vertex members taken (Point1f...Point10f). The Point type consumer does not care for the source's stride and the source supplies a zero for members greater than its stride. e.g. Point4f from a source of stride 3 would be filled with data[i + 0], data[i + 1], data[i + 2], 0.

Obviously DataSource could expose methods GetPoint1f(int index), GetPoint2f(int index) and the like. These types of solutions might be best given the fixed set of return types, element size, etc. However...

What are possible solutions if a syntax like…

Point3f point = SomeDataSource.ElementAt[index];

...or similar was requested/required/desired ?...pros/cons ?...examples of what not to do ?...harsh language ?

like image 915
Rusty Avatar asked Jan 27 '26 13:01

Rusty


2 Answers

What are possible solutions if a syntax like…

Point3f point = SomeDataSource.ElementAt[index];

...or similar was requested/required/desired ?

This is the prime candidate for a user-defined implicit conversion:

// I’m guessing it’s a struct, but can be a class too
public struct Point3f
{
    // ...

    public static implicit operator Point3f(double[] array)
    {
        // Just for demonstration: in real code,
        // please check length and nullity of array first!
        return new Point3f(array[0], array[1], array[2]);
    }

    // You can declare one that goes the other way too!
    public static implicit operator double[](Point3f point)
    {
        return new double[] { point.Px, point.Py, point.Pz };
    }
}
like image 96
Timwi Avatar answered Jan 30 '26 03:01

Timwi


How do you know the type of PointNf which is at index?

Anyway, the factory pattern is what you're after, but the question is how you will implement it given your objects. A basic factory would look something like this

public T GetElementAt<T>(int index) where T : new() {
    Type type = typeof(T);
    T result = new T()
    if (type==typeof(Point3f)) {
        result.X = data[index];
        result.Y = data[index+1];
        result.Z = data[index+2];
    }
    else if (type==typeof(Point2f) {
        result.X = data[index];
        result.Y = data[index+1];
    }
    return result;
}

NB: This won't compile because X, Y, Z aren't defined for T, but you don't wanna use this anyway.

The drawback is having to check for the type of T for each point type. There are several solutions to improve on it though if you are using your own PointNf classes which you can modify. An example would be to make each PointNf class derive from a common interface (IPointDataProvider) with a method like void PopulateData(double[] data, int index), for which they implement their own specifics, and your factory method can be reduced to

public T GetElementAt<T>(int index) where T : IPointDataProvider, new() {
    T result = new T()
    result.PopulateData(data, index)
    return result;
}

An example implementation of a point is as simple as.

class Point2f : IPointDataProvider {
    double X, Y;

    void IPointDataProvider.PopulateData(double[] data, int index) {
        X = data[0];
        Y = data[1];
    }
}
like image 31
Mark H Avatar answered Jan 30 '26 01:01

Mark H



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!