The problem is that you try to safe over C++ konwledge to C# ;-).
C# generics ant C++ templates have not much in common (except of the syntax similarity and the basic aim, but otherwise, the concepts are quite different).
In C#, the generic type argument has only "object" capabilities, that is
Equals()
,
GetHashCode()
,
GetType()
, and
ToString()
.
If you want to tell that the generic type argument has more capabilities, you must give a
type constraint to the generic argument, i.e. the actual types that may be passed as generic parameters are constraint to be of a given type.
E.g. in your example, if you want to be able to compare two values, you must tell this to the function.
If your primary purpose is to pass numeric values like
int
, then you have to check what interfaces
int
implements and then you can give that as constraint.
public struct Int32 : IComparable, IFormattable, IConvertible, IComparable<int>, IEquatable<int> { ... }
You now can check if all the numeric types share the same needed capabilities, namely comparing. This is given for the interaface
IComparable<T>
. Note that the non-generic interface
IComparable
has its roots in the times when C# did not know of generics.
So, your code should be implemented with a constraint:
public static void Swap<T>(ref T a, ref T b)
{ ... }
public static T MakeInRange<T>(T value, T min, T max) where T: IComparable<T>
{ ... CompareTo(...) ... }
In addition to that, the concept of
Swap()
is far less used in C# compared to C++. There is virtually no need for it since most of the types are reference types and the swap-idiom as used in C++ construction and assignment is not in use as far as I can judge.
So, an alternative to your code could look more C#-ish:
public static T Clip<T>(T val, T bottom, T top) where T : IComparable<T>
{
if (bottom.CompareTo(top) > 0) return Clip(val, top, bottom);
if (bottom.CompareTo(val) > 0) return bottom;
if (top.CompareTo(val) < 0) return top;
return val;
}
Cheers
Andi