0

I have the a method with the following signature;

private static void CheckValue<T>(ref Double result, Int64 value, String condition, T checkValue) where T : class{};

The checkValue can be a Double or an Int64. However it gives the following error;

Operator '>=' cannot be applied to operatands of type 'long' and 'T'

Because I want a generic function and do not want to define two functions (One with the Int64 checkValue and one with the Double checkValue signature), I came up with T.

I used the where T : class, this way it limits T to classes and can use operators. (Found this on the following topic): How to solve Operator '!=' cannot be applied to operands of type 'T' and 'T'

I can imagine that this works if I can restrain T to only Int64 or Double. However if I change the following in the signature:

where T : class, Int64, Double

It gives the same error.

@Edit - 06-08-2015 11:16 My bad, If I run the prior it gives an error about the Int64 and Double in the where clause. (It is not a valid constraint)

Community
  • 1
  • 1
Revils
  • 1,478
  • 1
  • 14
  • 31
  • How would you compare a class `Foo` with a `long`? How would the compiler know how to do that? – Yuval Itzchakov Aug 06 '15 at 09:16
  • 2
    Write two methods one for long and one for double. No need for generics here – Sriram Sakthivel Aug 06 '15 at 09:18
  • I think this is a known limitation of generics in C#. – Alex Booker Aug 06 '15 at 09:18
  • There is no need indeed, I am just curious how I could solve it with a generic T. – Revils Aug 06 '15 at 09:19
  • 2
    If you have a function that only works for two input types then it's not generic. – Lee Aug 06 '15 at 09:20
  • 1
    You can't solve it. The purpose of generics is to accept *any* type. Yes, there are constraints but these are also limited. There is no way for the compiler to verify that it is possible to compare the given value to anything at all. – Lasse V. Karlsen Aug 06 '15 at 09:20
  • @Lee, Im not saying its totally generic. I am just curious how I could use generics to solve this problem. – Revils Aug 06 '15 at 09:22
  • You can't(at least without getting the hands dirty). – Sriram Sakthivel Aug 06 '15 at 09:22
  • You could pass in a `Func` containing the comparison you want to do, it's hard to say without seeing the implementation of `CheckValue`. – Lee Aug 06 '15 at 09:26
  • You can use a common interface implemented by both Double and Int64, perhaps something like `where T : class, IConvertible`. But this does not limit you however to only `Double and Int64` – jmc Aug 06 '15 at 09:27

2 Answers2

1

The checkValue can be a Double or an Int64

No it can't. You've got where T : class as a constraint to insist that T is a reference type, so T can be neither of those things. You in fact what to insist upon the opposite:

private static void CheckValue<T>(ref Double result, Int64 value, String condition, T checkValue) where T : struct
{
}

Operator '>=' cannot be applied to operatands of type 'long' and 'T'

Well it can't. You need to have a specific type which >= can be used with.

You can though depend upon the fact that both long and double implement IComparable. I've no idea what you actually want to do in your implementation, but the following works:

private static void CheckValue<T>(ref Double result, Int64 value, String condition, T checkValue) where T : struct, IComparable
{
  if(checkValue is long)
    result = checkValue.CompareTo(value) >= 0 ? 1.0 : -1.0;
  else if(checkValue is double)
    result = checkValue.CompareTo((double)value) >= 0 ? 1.0 : -1.0;
  else
    throw new Invalid‎OperationException();
}

Because I want a generic function and do not want to define two functions (One with the Int64 checkValue and one with the Double checkValue signature), I came up with T.

While the above works, I'd recommend you do have separate methods here. The result will be faster (no runtime check on type, and faster comparison call) and more type-safe (no chance of the runtime check on type failing). It's worth noting for comparison that many framework methods have overloads on different primitive types, even in methods that were first introduced to the framework after generics where added to .NET, for these reasons.

(I'd also note that using ref is often best avoided, especially since you aren't returning any other value forcing you into using ref. Could you instead accept Double result and return a double, with the replacement of the value happening where the call is made rather than inside this method?)

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
0

There is no need to implement it using generics as you are comparing a double or an int with an Integer value. But if you some implementation with generics , then Just have a signature like this.

 private static void CheckValue<T>(ref Double result, int value, String condition, T checkValue) where T : struct
        {
            if (value.Equals(checkValue))
                result=1; // do anything you want here
            else
                result=0;
        }