代码之家  ›  专栏  ›  技术社区  ›  Rusty

基于调用者的类型生成返回类型的动态/泛型/其他方法有哪些示例?

  •  3
  • Rusty  · 技术社区  · 14 年前

    给定一个数据源对象,该对象按索引从一个double数组中提供顶点,其中一个顶点包含10个double,其成员为Px、Py、Pz、Nx、Ny、Nz、S、T、U、V,而backing数组包含所有 基于数据源的步长、偏移和计数属性的顶点成员的任何子集。数据源可以简化为:

      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)。点类型使用者不关心源的步幅,并且源为大于其步幅的成员提供零。e、 g.第3步来源的第4f点将填充数据[i+0],数据[i+1],数据[i+2],0。

    显然,DataSource可以公开GetPoint1f(int index)、GetPoint2f(int index)等方法。如果给定固定的返回类型集、元素大小等,这些类型的解决方案可能是最好的。。。

    Point3f point = SomeDataSource.ElementAt[index];
    

    2 回复  |  直到 14 年前
        1
  •  5
  •   Timwi    14 年前

    如果语法像

    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 };
        }
    }
    
        2
  •  1
  •   Mark H    14 年前

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

    注意:这不会编译,因为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];
        }
    }