27

I'm trying to compare an object with an int value such as

if (myObject - 5 == 0)
    doSomething();

my class could look something like this: (most setters/getters removed, so don't mind that all variables are private)

public class SomeClass
{
    public string name;
    private int minValue;
    private int maxValue;
    private int currValue;

    public int getCurrentValue()
    {
        return currValue;
    }
}

What I'm trying to achieve is something like this:

someClassInstance - 5;

to be equal

someClassInstance.getCurrentValue() - 5;

Can I make an override for the object to act as an int (it's own variable) opposed to just being an object?

Creative Magic
  • 3,143
  • 3
  • 28
  • 47
  • 1
    possible duplicate of [How to add or subtract two instances of the same class/type](http://stackoverflow.com/questions/10390995/how-to-add-or-subtract-two-instances-of-the-same-class-type) – Tim Schmelter Jan 29 '14 at 08:44
  • Dmitry's answer below is excellent, but just ask yourself if it makes sense to use an unary operator like that. For example: "myCar + hisCar" would make it difficult to understand what operation is being done. – Fredrik Jan 29 '14 at 08:53
  • I am blown away by how cool Dmitry Bychenko answer is, but I somewhat prefer Matthew Watson since it seems more efficient performance wise. – Creative Magic Jan 29 '14 at 08:58
  • I don't thing this question should be closed because of @Matthew Watson answer that is not available on the other answer. – Creative Magic Jan 29 '14 at 09:04
  • @CreativeMagic: a duplicate can contain better answers as the original, actually this is often the case. It should be closed as duplicate anyway. Note that closing does not mean that it gets deleted, both questions will be linked together. – Tim Schmelter Jan 29 '14 at 10:06

3 Answers3

47

May be operator is the case?

public class SomeClass {
  ...

  public static int operator -(SomeClass left, int right) {
    if (Object.ReferenceEquals(null, left))
      throw new ArgumentNullException("left");

    return left.getCurrentValue() - right;
  }
}

...

SomeClass someClassInstance = new SomeClass(...);

int result = someClassInstance - 5;

Another possibility (based on implicit operator) is to convert SomeClass implicitly to int whenever required:

public class SomeClass {
  ...

  // Whenever int is requiered, but SomeClass exists make a conversion
  public static implicit operator int(SomeClass value) {
    if (Object.ReferenceEquals(null, value))
      throw new ArgumentNullException("value");

    return value.getCurrentValue();
  }
}

...

SomeClass someClassInstance = new SomeClass(...);

int result = someClassInstance - 5;
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • +1 worth noting that he should better use a immutable value type, so a `struct` instead of class. To quote E.Lipper: _"this is precisely the sort of job that immutable value types were designed for"_ – Tim Schmelter Jan 29 '14 at 08:57
  • Just as a question, will this work with int conversion operator overloaded: int result = 5 - classInstance; ? – besworland Jan 29 '14 at 08:59
  • 1
    @besworland: "int result = 5 - classInstance" will not work with "-" operator (you should implement "int operator -(int left, SomeClass right)" in addition to existing one - arguments order matters); but it will work with implicit operator – Dmitry Bychenko Jan 29 '14 at 09:05
16

Actually you would be much better off overriding operator int, that way you can do far more calculations with less overloads:

using System;

namespace Demo
{
    public class SomeClass
    {
        public string name;
        private int minValue;
        private int maxValue;
        public int currValue;

        public int getCurrentValue()
        {
            return currValue;
        }

        public static implicit operator int(SomeClass value)
        {
            if (value == null)
                throw new ArgumentNullException("value");

            return value.currValue;
        }
    }

    internal class Program
    {
        private void run()
        {
            var test = new SomeClass {currValue = 5};

            if (test - 5 == 0)
                Console.WriteLine("It worked");

            if (test + 5 == 10)
                Console.WriteLine("This also worked");
        }

        private static void Main()
        {
            new Program().run();
        }
    }
}
Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • This one seems even better, then operator - overloading! Cool, always good to learn something new! :) – besworland Jan 29 '14 at 08:55
  • 1
    You do have to be careful with implicit conversions though - you can accidentally pass something to a method that expects an `int` and it will silently convert it for you. If you don't want that kind of behaviour, you can change `implicit` to `explicit` and then you have to add an explicit cast to `int`. – Matthew Watson Jan 29 '14 at 09:16
1

You could experiment with a mixture of implicit conversions and operator overloading, but from my experience you will never make it work as seamlessly as you wish (and as you could get it to work in C++).

If I were you, I would change the getCurrentValue to a property:

public int CurrentValue
{
    get {return currValue};
}

and just use someClassInstance.CurrentValue -5

Grzenio
  • 35,875
  • 47
  • 158
  • 240