用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#泛型专门化一个值

与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显然不是一个通用参数。TSizeTSize并没有描述这个类型是做什么的,它只是描述了它是如何变化的。相反,您应该将其命名为TValue

做这种事情的唯一方法是向Size添加接口约束,要求Size具有MaxMin方法或类似的东西。当然,在这种情况下就不再需要定义了。

假设你想要完成的是在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;

不编译