Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何实现方法在结构上是泛型的C#泛型类?_C#_Struct - Fatal编程技术网

如何实现方法在结构上是泛型的C#泛型类?

如何实现方法在结构上是泛型的C#泛型类?,c#,struct,C#,Struct,假设我们有这对结构,它是广泛使用的交换格式的一部分(因此我们不能修改源代码——理想情况下也不应该这样做:我们不想改变数据本身): struct Vector2{public int x;public int y;} 结构向量3{public int x;public int y;public int z;} 以及一个类,其核心是一个或另一个的列表,并且包含许多算法,这些算法对于两个结构的实现几乎相同,但必须引用3元素结构中的额外成员(thez): 公共类网格 { 私有列表_myVectors;

假设我们有这对结构,它是广泛使用的交换格式的一部分(因此我们不能修改源代码——理想情况下也不应该这样做:我们不想改变数据本身):

struct Vector2{public int x;public int y;}
结构向量3{public int x;public int y;public int z;}
以及一个类,其核心是一个或另一个的列表,并且包含许多算法,这些算法对于两个结构的实现几乎相同,但必须引用3元素结构中的额外成员(the
z
):

公共类网格
{
私有列表_myVectors;
}
…您如何正确实现处理它们的一套方法?e、 g:

public int Average()
{
//如果矢量2:
整数和=0,计数=0;
foreach(var v2 in_MyVectors)
{
总和+=v2.x+v2.y;
计数++;
}
//如果矢量3:
整数和=0,计数=0;
foreach(向量中的变量v3)
{
总和+=v3.x+v3.y+v3.z;
计数++;
}
返回和/计数;
}
特别注意:特定于结构的方法已经存在(数以百万计),由缺乏任何内置泛型的API提供。因此,例如,我们可以自信地编写一个算法来使用
外国API
中的方法,知道源代码的一个副本(但使用泛型)将绑定到一个可接受的实现:

public float-FOREIGN\u-API\u-Average(矢量2输入);
公共浮点数国外平均值(矢量3输入);

我在这里想解决的问题大致如下:

  • 上面示例中的
    //if Vector2:
    概念部分我不知道如何在C#中实现
  • 我只是不知道如何构建这个。我觉得我必须做一些巧妙的技巧来说明“我有任意的泛型参数。但是我有这个类的一些特定版本,我将在内部实现。(所有其他非特定版本都是非法的,我将实现一组抛出异常的方法)”。但是我不知道该怎么办
  • 结构不能相互“扩展”。如果它们是类,我将首先用
    约束using类(Mesh),其中T:BaseVector
    ,然后从那里开始。但这在结构中是不可能的
  • 这些结构来自一个我不拥有的(十亿美元)软件;有很多架构决策我希望他们做出不同的决定,但是TL;医生:要用我们现有的东西
  • 这个问题不仅仅是两个结构:为了支持3D数学,我必须重新实现
    Vector1
    Vector2
    Vector3
    Vector4
    。。。有很多代码我不想复制/复制
  • …典型的网格类有4个内部列表,每个列表可以是这4种类型中的任意一种。如果我必须手工编写每个组合,而不是使用泛型,我将有相同代码的4^4=256个副本要编写和维护

  • 我的建议是让Vector2和Vector3自带处理方法。接口是您正在寻找的droid:

    • 让他们实现一个具有您所需功能的接口
    • 使用该接口作为列表中任何内容的类型
    • 调用接口函数
    展会流程的合适名称为“Sumable”

    这些可能是的内置实现。当然,这两者不能被继承。但是MVVM的做法是:“如果您不能继承或修改它,请将它包装成您可以继承和修改的内容。”

    围绕实现接口的向量之一的简单包装器(可以是结构或类)就是您所需要的

    另一种选择是使用LINQ进行处理。如果这只是一个一次性的过程,那么它通常要轻得多,而不是深入到本质、类、接口等方面。

    (我认为这不管用,但这是我一开始尝试的方向-欢迎评论,也许它会激励其他人提供更好的答案:)

    <>我想我可以做一些事情(比如C++中的,如果我记得正确,C没有直接等价于完全一般的情况,但我想对于这样的简单情况,可能有一个等价的):

    公共类网格
    {
    //这个类在运行时基本上会失败:
    //它不能/不会阻止您实例化它
    //比如说,一个网格,它根本不能
    //要明智地执行。
    //
    //所以:很多方法都会抛出异常——但有些方法是可以实现的
    //(因此:在该类的所有其他变体中共享)
    公开名单;
    public int CountElements(){return internalList.Count;}
    public int DoSomethingToList1(){…}
    }
    公共类网格
    {
    //现在我们说:嘿,编译器!我将手动重写
    //所有情况下网格的通用实例,其中
    //T1是矢量2!
    public int DoSomethingToList1(){…}
    }
    

    或者另一次试图找到一种语法上有效的方法来做同样的事情(c.f.@Gserg对主要问题的评论)——但显然这失败了,因为c#编译器禁止任意类型转换:

        private List<T1> data;
        public void Main()
        {
            if( typeof(T1) == typeof(Vector2) )
                Main( (List<Vector2>) data );
            else if( typeof(T1) == typeof(Vector3) )
                Main( (List<Vector3>) data );
        }
    
        public void Main( List<Vector2> dataVector2s )
        {
            ...
        }
        public void Main( List<Vector3> dataVector3s )
        {
            ...
        }
    
    私有列表数据;
    公共图书馆
    {
    if(typeof(T1)=typeof(Vector2))
    主要((列表)数据);
    else if(typeof(T1)=typeof(Vector3))
    主要((列表)数据);
    }
    公用void Main(列出数据向量2s)
    {
    ...
    }
    公共void Main(列出数据向量3s)
    {
    ...
    }
    
    <>代码>真的让你嫉妒C++和他们愚蠢的性感模板,不是吗? 首先是一些假设(如果错误,请更正):

    你说过网格类型可以有四个不同的列表,所以我假设它的signa
        private List<T1> data;
        public void Main()
        {
            if( typeof(T1) == typeof(Vector2) )
                Main( (List<Vector2>) data );
            else if( typeof(T1) == typeof(Vector3) )
                Main( (List<Vector3>) data );
        }
    
        public void Main( List<Vector2> dataVector2s )
        {
            ...
        }
        public void Main( List<Vector3> dataVector3s )
        {
            ...
        }
    
    public static class VectorExtensions
    {
        public static int Sum<TVector>(this IEnumerable<TVector> vectors)
        {
            var type = typeof(TVector);
            if (type == typeof(Vector1))
            {
                return FOREIGN_API.Sum((IEnumerable<Vector1>)vectors);
            }
            else if (type == typeof(Vector2))
            {
                return FOREIGN_API.Sum((IEnumerable<Vector2>)vectors);
            }
            else if (...) // etc.
    
            throw new ArgumentException($"Invalid type of vector {typeof(TVector).Name}.");
        }
    }
    
    public class Mesh<T1, T2, T3, T4>
    {
        private List<T1> _myVectors1;
        private List<T2> _myVectors2;
        private List<T3> _myVectors3;
        private List<T4> _myVectors4;
    
        public float Average()
        {
            var sum1 = _myVectors1.Sum();
            var sum2 = _myVectors2.Sum();
            var sum3 = _myVectors3.Sum();
            var sum4 = _myVectors4.Sum();
    
            return (float)(sum1 + sum2 + sum3 + sum4) / 
                (_myVectors1.Count + _myVectors2.Count + _myVectors3.Count + _myVectors4.Count);
        }
    }
    
    public static class VectorExtensions
    {
        public static int Sum<TVector>(this IEnumerable<TVector> vectors) =>
            FOREIGN_API.Sum((dynamic)vectors);
    }
    
    public interface IVectorOperations<TVector>
    {
        public int Sum(TVector vector);
    
        public int Sum(IEnumerable<TVector> vectors);
    }
    
    public class VectorOperations1 : IVectorOperations<Vector1>
    {
        public int Sum(Vector1 vector) => vector.x;
    
        public int Sum(IEnumerable<Vector1> vectors) => vectors.Sum(v => Sum(v));
    }
    
    
    public class VectorOperations2 : IVectorOperations<Vector2>
    {
        public int Sum(Vector2 vector) => vector.x + vector.y;
    
        public int Sum(IEnumerable<Vector2> vectors) => vectors.Sum(v => Sum(v));
    }
    
    public static class VectorOperations
    {
        public static IVectorOperations<TVector> GetFor<TVector>()
        {
            var type = typeof(TVector);
    
            if (type == typeof(Vector1))
            {
                return (IVectorOperations<TVector>)new VectorOperations1();
            }
            else if (...) // etc.
    
            throw new ArgumentException($"Invalid type of vector {typeof(TVector).Name}.");
        }
    }
    
    public class Mesh<T1, T2, T3, T4>
    {
        private List<T1> _myVectors1;
        private List<T2> _myVectors2;
        private List<T3> _myVectors3;
        private List<T4> _myVectors4;
        private readonly IVectorOperations<T1> _operations1;
        private readonly IVectorOperations<T2> _operations2;
        private readonly IVectorOperations<T3> _operations3;
        private readonly IVectorOperations<T4> _operations4;
    
        public Mesh()
        {
            _operations1 = VectorOperations.GetFor<T1>();
            _operations2 = VectorOperations.GetFor<T2>();
            _operations3 = VectorOperations.GetFor<T3>();
            _operations4 = VectorOperations.GetFor<T4>();
        }
    
        public float Average()
        {
            var sum1 = _operations1.Sum(_myVectors1);
            var sum2 = _operations2.Sum(_myVectors2);
            var sum3 = _operations3.Sum(_myVectors3);
            var sum4 = _operations4.Sum(_myVectors4);
    
            return (float)(sum1 + sum2 + sum3 + sum4) / 
                (_myVectors1.Count + _myVectors2.Count + _myVectors3.Count + _myVectors4.Count);
        }
    }
    
    public static class VectorOperations
    {
        private static VectorOperations1 Implementation1 = new VectorOperations1();
        private static VectorOperations2 Implementation2 = new VectorOperations2();
        ... // etc.
    
        public static IVectorOperations<TVector> GetFor<TVector>()
        {
            var type = typeof(TVector);
    
            if (type == typeof(Vector1))
            {
                return (IVectorOperations<TVector>)Implementation1;
            }
            else if (...) // etc.
    
            throw new ArgumentException($"Invalid type of vector {typeof(TVector).Name}.");
        }
    }
    
    public class Mesh<T1, T2, T3, T4>
    {
        private List<T1> _myVectors1;
        private List<T2> _myVectors2;
        private List<T3> _myVectors3;
        private List<T4> _myVectors4;
        private static readonly IVectorOperations<T1> Operations1 =
            VectorOperations.GetFor<T1>();
        private static readonly IVectorOperations<T2> Operations2 =
            VectorOperations.GetFor<T2>();
        private static readonly IVectorOperations<T3> Operations3 =
            VectorOperations.GetFor<T3>();
        private static readonly IVectorOperations<T4> Operations4 =
            VectorOperations.GetFor<T4>();
    
        public float Average()
        {
            var sum1 = Operations1.Sum(_myVectors1);
            var sum2 = Operations2.Sum(_myVectors2);
            var sum3 = Operations3.Sum(_myVectors3);
            var sum4 = Operations4.Sum(_myVectors4);
    
            return (float)(sum1 + sum2 + sum3 + sum4) / 
                (_myVectors1.Count + _myVectors2.Count + _myVectors3.Count + _myVectors4.Count);
        }
    }