Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
hi in the following code:
C#
namespace General
{
	public static class GlobalFunctions
	{
		public static void Swap<T>(ref T a, ref T b)
		{
			T c = a;
			a = b;
			b = c;
		}

		public static T MakeInRange<T>(T value, T min, T max)
		{
			if (min > max) Swap(ref min, ref max);
			return (min > value) ? min : (value > max) ? max : value;
		}
	}
}

i get the following error in the second function:
error CS0019: Operator '>' cannot be applied to operands of type 'T' and 'T'

while no T is used that > be meaningless for it. sometimes int is used, sometimes float and sometimes double. what's the problem?
thx
Posted
Updated 8-Apr-12 0:42am
v2

Hi,
The problem is that, sometime it can be Person, Animal, Book, ... as it is generic and >,< definition is different in these objects. In order to do that you need to use Operator Overloading. Take a look at this post:
Operator Overloading with Generics[^]

I hope it will help,
Cheers.
 
Share this answer
 
Comments
ilostmyid2 8-Apr-12 6:58am    
ok, in such cases i will define the operator for the class i pass as T, i promise! otherwise compiler has right to generate error! in C++ it doesn't generate such an error until it sees that i've called an undefined operator. why here is not so?
going to read the document.
thx
ilostmyid2 8-Apr-12 7:13am    
i read the document, but have to honestly confess that i couldn't understand it, because it was too complex for me! :D
C#
public static class GlobalFunctions
    {
        public static void Swap<t>(ref T a, ref T b)
        {
            T c = a;
            a = b;
            b = c;
        }

        public static T MakeInRange<t>(T value, T min, T max) where T:IComparable<t>
        {
            if (min.CompareTo(max)>0) Swap(ref min, ref max);
            return (min.CompareTo(value)>0) ? min : (value.CompareTo(max)>0) ? max : value;
        }
    }</t></t></t>
 
Share this answer
 
Comments
ilostmyid2 8-Apr-12 7:15am    
the same problem must exist here too. how come T has a method called CompareTo?
majune 8-Apr-12 7:53am    
Use constraint to make T base on IComparable.
"where T:IComparable<t>"
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.

C#
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:
C#
public static void Swap<T>(ref T a, ref T b) // no constrain needed
{ ... }
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:
C#
/// <summary>
/// Clip the value to be within the range bottom...top
/// (top and bottom may be given in wrong order).
/// </summary>
/// <typeparam name="T">IComparable type, e.g. int, double, etc.</typeparam>
/// <param name="val">the value to clip</param>
/// <param name="bottom">lower bound</param>
/// <param name="top">upper bound</param>
/// <returns>the value if it is within the given range,
/// otherwise the boundary that is closer to the given value</returns>
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
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900