Каковы некоторые примеры динамических / общих / других методов для генерации возвращаемого типа на основе типа вызывающего? - PullRequest
3 голосов
/ 02 сентября 2010

В контексте C #, .Net 4 ...

Учитывая объект источника данных, который предоставляет вершины по индексу из массива двойников, где вершина содержит десять двойников с членами Px, Py, Pz,Nx, Ny, Nz, S, T, U, V. и вспомогательный массив содержит все или любое подмножество элементов вершины, основанное на свойствах шага, смещения и счетчика источника данных.Источник данных может быть упрощен как:

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

Некоторым потребителям будет интересен тип возвращаемого значения double [], но большинство будет запрашивать данные как тип PointNf, где N - число взятых членов вершины (Point1f ... Point10f).Потребитель типа Point не заботится о шаге источника, и источник предоставляет ноль для элементов, превышающих его шаг.например, Point4f из источника шага 3 будет заполнен данными [i + 0], данными [i + 1], данными [i + 2], 0.

Очевидно, DataSource может предоставлять методы GetPoint1f (int index), GetPoint2f (int index) и тому подобное.Эти типы решений лучше всего подходят, учитывая фиксированный набор типов возвращаемых данных, размер элемента и т. Д. Однако ...

Каковы возможные решения, если синтаксис, такой как ...

Point3f point = SomeDataSource.ElementAt[index];

...или подобное было запрошено / обязательно / желательно? ... плюсы / минусы? ... примеры чего не делать? ... грубый язык?

Ответы [ 2 ]

5 голосов
/ 02 сентября 2010

Каковы возможные решения, если такой синтаксис, как…

Point3f point = SomeDataSource.ElementAt[index];

... или аналогичный был запрошен / необходим / желателен?

Это основной кандидатдля пользовательского неявного преобразования:

// 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 };
    }
}
1 голос
/ 02 сентября 2010

Откуда вы знаете тип PointNf, который находится на index?

В любом случае, заводской шаблон - это то, что вам нужно, но вопрос в том, как вы будете реализовывать его с учетом ваших объектов. Базовая фабрика будет выглядеть примерно так

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: Это не скомпилируется, потому что X, Y, Z не определены для T, но вы все равно не хотите использовать это.

Недостатком является необходимость проверки типа T для каждого типа точки. Есть несколько решений, чтобы улучшить его, хотя, если вы используете свои собственные классы PointNf, которые вы можете изменить. Примером может служить вывод каждого класса PointNf из общего интерфейса (IPointDataProvider) с помощью метода, подобного void PopulateData(double[] data, int index), для которого они реализуют свои собственные особенности, а ваш фабричный метод может быть сокращен до

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

Пример реализации точки так же прост, как.

class Point2f : IPointDataProvider {
    double X, Y;

    void IPointDataProvider.PopulateData(double[] data, int index) {
        X = data[0];
        Y = data[1];
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...