如何实现方法在结构上是泛型的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元素结构中的额外成员(thez
):
公共类网格
{
私有列表_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
,然后从那里开始。但这在结构中是不可能的Vector1
,Vector2
,Vector3
,Vector4
。。。有很多代码我不想复制/复制李>
我的建议是让Vector2和Vector3自带处理方法。接口是您正在寻找的droid:
- 让他们实现一个具有您所需功能的接口
- 使用该接口作为列表中任何内容的类型
- 调用接口函数
公共类网格
{
//这个类在运行时基本上会失败:
//它不能/不会阻止您实例化它
//比如说,一个网格,它根本不能
//要明智地执行。
//
//所以:很多方法都会抛出异常——但有些方法是可以实现的
//(因此:在该类的所有其他变体中共享)
公开名单;
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);
}
}