用c#泛型专门化一个值
本文关键字:一个 泛型 专门化 | 更新日期: 2023-09-27 18:13:58
我有一些实现基本Pixel
类的c++代码。以下是我所拥有的重要比特的一小部分:
// Pixel.h
template <class SizeType>
struct Pixel
{
public:
typedef SizeType Size;
Size R;
Size G;
Size B;
static Size Min;
static Size Max;
TPixel(Size R = Min, Size G = Min, Size B = Min);
};
#include "Pixel.impl"
// Pixel.impl
template <class SizeType> SizeType Pixel<SizeType>::Min = std::numeric_limits<Size>::min();
template <class SizeType> SizeType Pixel<SizeType>::Max = std::numeric_limits<Size>::max();
template <> float Pixel<float>::Min = 0;
template <> float Pixel<float>::Max = 1;
template <> double Pixel<double>::Min = 0;
template <> double Pixel<double>::Max = 1;
在c#中,我试图复制这个:
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
public static const Size Min; // What should I do here?
public static const Size Max;
}
除了我不知道如何将这个最小/最大大小包含到类型中。我希望能够有一个统一的像素界面,允许你做像夹紧,添加,缩放等事情。
当我试图处理可能任意类型的向量和矩阵时,我遇到了类似的解决方案。谁能告诉我如何才能完成上面的c++代码是做什么?
与c++模板特化不同,. net中没有泛型特化。
你不能初始化T
实例为T
以外的任何东西,除非你有约束,所以你不能使用静态构造函数来尝试解决这个问题。
据我所知,没有任何约束允许您只指定数字类型或从数字类型转换的类型。
我建议你创建两种不同类型的类:
public struct PixelFloat
{
public float R { get; set; }
public float G { get; set; }
public float B { get; set; }
public const float Min = 0.0f;
public const float Max = 1.0f;
}
public struct PixelDouble
{
public double R { get; set; }
public double G { get; set; }
public double B { get; set; }
public const double Min = 0.0f;
public const double Max = 1.0f;
}
无论如何,这实际上是相同的东西,因为这是它在幕后编译成的。与此相比,其他解决方案不会给您带来太多好处,因为您仍然需要键入类型:Pixel<double>
Pixel<float>
。
同样,在这种情况下,我建议您使用显示您正在使用泛型参数类型的名称。Size
显然不是一个通用参数。TSize
。TSize
并没有描述这个类型是做什么的,它只是描述了它是如何变化的。相反,您应该将其命名为TValue
。
做这种事情的唯一方法是向Size
添加接口约束,要求Size
具有Max
和Min
方法或类似的东西。当然,在这种情况下就不再需要定义了。
假设你想要完成的是在c#泛型中做模板专门化,这是不可能的。
这是一个MSDN链接,比较了两者之间的差异,但重点是:
- c#不支持显式特化;也就是说,一个特定类型的模板的自定义实现。
- c#不支持部分专门化:对类型参数子集的自定义实现。
你必须这样做:
static class Pixel
{
public static Size Min<Size>() where Size : struct;
public static Size Max<Size>() where Size : struct;
}
struct Pixel<Size> where Size : struct
{
public Size R;
public Size G;
public Size B;
}
然后这样命名:
Pixel<double> doublePixel;
var max = Pixel.Max<double>();
这对你有用吗?
也许是这样的?
public struct Pixel<Size> where Size : struct
{
private enum DEF_TYPES
{
MIN,
MAX
}
private static Dictionary<Type, Dictionary<DEF_TYPES, object>> m_Defs = new Dictionary<Type, Dictionary<DEF_TYPES, object>>
{
{
typeof(float),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0f},
{DEF_TYPES.MAX, 1f}
}
},
{
typeof(double),
new Dictionary<DEF_TYPES, object> {
{DEF_TYPES.MIN, 0d},
{DEF_TYPES.MAX, 1d}
}
}
};
private static Size GetValue(DEF_TYPES def_type)
{
if(!m_Defs.ContainsKey(typeof(Size)))
throw new ArgumentException("No default values for template " + typeof(Size));
if(!m_Defs[typeof(Size)].ContainsKey(def_type))
throw new ArgumentException("No default value '" + def_type + "' for template " + typeof(Size));
return (Size)m_Defs[typeof(Size)][def_type];
}
public Size R;
public Size G;
public Size B;
public static readonly Size Min = GetValue(DEF_TYPES.MIN);
public static readonly Size Max = GetValue(DEF_TYPES.MAX);
}
并用作:
Console.WriteLine(Pixel<float>.Max);
Console.WriteLine(Pixel<float>.Min);
Console.WriteLine(Pixel<double>.Max);
Console.WriteLine(Pixel<double>.Min);
;
Pixel<double>.Min = 4;
不编译