Specialize value with C # generators?

I have C ++ code that implements the Pixel base class. Here is just a stub of the important bits that I have:

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

And in C # I am trying to duplicate this:

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

Also, I have no idea how I can include this Min / Max size in a type. I would like to have a single Pixel interface that allows you to do things like clip, add, scale, etc.

I come across a similar solution when I try to deal with vectors and matrices of a potentially arbitrary type. Can anyone advise me how I can accomplish what the above C ++ code does?

+4
source share
5 answers

Unlike the specialized specialization of C ++, there is no such specialization as the specialization in .Net.

You cannot initialize an instance of T for anything other than T unless you have a restriction, so you cannot use a static constructor to try to work around the problem.

As far as I know, there are no restrictions, which allows you to specify only types that are either numeric types or have conversions from numeric types.

I suggest you just make two different types of classes:

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

This is actually the same thing, since this is what he compiled under the covers. Other solutions will not buy you compared to this, because you still have to type in: Pixel<double> Pixel<float> .

In addition, in such cases, I suggest you use names that indicate that you are using types from your general parameters. Size not, obviously, a general parameter. TSize is. And TSize does not describe what the type does, it just describes how it changes. Instead, you should call it something like TValue .

+3
source

The only way to do this is to add an interface restriction on Size , for which Size should have the Max and Min methods or something like that. Of course, in this case definitions are no longer needed.

+1
source

Assuming you are trying to do specialized specialization in C # generics, this is not possible.

Here is the MSDN link comparing the differences between them, but the main points:

  • C # does not support explicit specialization; that is, a custom template implementation for a particular type.
  • C # does not support partial specialization: a custom implementation for a subset of type arguments.
0
source

You would need to do something like this:

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

And then call it like this:

 Pixel<double> doublePixel; var max = Pixel.Max<double>(); 

Does this work for you?

0
source

Something like this, maybe?

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

And used as:

 Console.WriteLine(Pixel<float>.Max); Console.WriteLine(Pixel<float>.Min); Console.WriteLine(Pixel<double>.Max); Console.WriteLine(Pixel<double>.Min); 

and

 Pixel<double>.Min = 4; 

Will not compile as expected.

Not perfect, but it works.

0
source

Source: https://habr.com/ru/post/1380307/


All Articles