2

Does C# classes inherit custom operators from base classes? I'm trying the following code:

class Person
{
    public int Age;

    public static Person operator ++(Person p)
    {
        p.Age++;
        return p;
    }
}

class Agent : Person {   }

static void Main(string[] args)
{
    Person p = new Person { Age = 23 };
    Console.WriteLine ( "Before increment : {0}" , p.Age );

    p++;
    Console.WriteLine("After increment : {0}", p.Age);

    Agent agent = new Agent { Age = 25 };
    Console.WriteLine("Before increment : {0}", agent.Age);

    agent++;
    Console.WriteLine("After increment : {0}", agent.Age);

}

The compiler told me that he cannot explicitly convert from Person to Agent.

I tried :

Agent agent = new Agent();
Person person = agent ++

But the same compiler message appear.

4
  • In what line the error occurs? Commented Nov 1, 2013 at 10:21
  • Error occurs when i try to increment the 'agent' variable. Commented Nov 1, 2013 at 10:24
  • 3
    The title of your question does not seem to have anything to do with the content. Commented Nov 1, 2013 at 10:33
  • possible duplicate of operator overloading and inheritance c# Commented Nov 1, 2013 at 11:00

5 Answers 5

6

The problem you are having is not based on whether or not the operator is inherited but due to the return type of the operator.

However in the case of an assigning operator you will have an issue with the return type of the operator

The expression x++ is a short hand for

x = x + 1

And in your case you are returning a Person and trying to assign that to an Agent. Written out that would be

agent.Age++;
agent = (Person)agent; //the cast is implicit and a result of the return type

You can only assign to a more generalized type. So assigning an Agent to a Person would work which is why the compiler will allow the return type to be a specialization of the implementing type (as is the case below).

You can accomplish what you are looking for with a bit of generics trickery

class Person<T> where T : Person<T>, new()
{
    public int Age;

    //taking advantage of the fact that the return type might be a specialization
    //of the type implementing the operator
    public static T operator ++(Person<T> p)
    {
        return new T { Age = p.Age + 1 };   
    }
}

class Agent : Person<Agent> { }

//Only required if Person should be usable on it's own
class Person : Person<Person> { }

The above operator constructs a new object which to me is inline with the contract of the ++operator but also requires a default constructor, if you wish you can do it with a cast instead.

public static T operator ++(Person<T> p)
{
    p.Age++;
    return (T)p;
}

Whether or not the operator is inherited is a matter of how you define inheritance.

The C# specifications uses "inheritance" in a different manner than the CLI specifications. The way the C# specs uses inheritance is in the the context of operators and static methods incompatible with the CLI specification (Ie the C# spec contradict the CLI specifications and as such the platform C# runs on does not support the specifications)

To out line why my money is on "operators are not inherited" is that they are syntax sugar for a static method.

[SpecialName]
public static T op_increment(Person<T> p)
{
    return new T { Age = p.Age + 1 };   
}

That's the implementation of a static method. According to the CLI specifications then static methods are not inherited:

A derived object type inherits all of the instance and virtual methods of its base object type. It does not inherit constructors or static methods.

below is an implementation of the ++ operator

public static T operator ++(Person<T> p)
{
    return new T { Age = p.Age + 1 };   
}

The IL for both of these two implementations is identical

Sign up to request clarification or add additional context in comments.

13 Comments

Wrong, check out my answer
I tied "Person person = agent ++" and it didn't work.The compiler complain about the same conversion problem.
This isn't even valid C# code. The parameter type of a unary operator must be the containing type (in this case, Person<T>, not T). The code in this answer won't actually compile.
@RuneFS It is defined, check out my answer with relevant link.
@SriramSakthivel you have linked to c++ specifications
|
2

Operators are implemented as static and inheritance does not apply to static members.

Some operators will work with derived types, some will not. It is a matter of type conversion rules.

But basically, Person p = ...; p++; is a very bad idea anyway. When you use operator overloading where it is appropriate you won't run into problems like this.

Comments

2

Update:

Like other members, operators declared in a base class are inherited by derived classes. Because operator declarations always require the class or struct in which the operator is declared to participate in the signature of the operator, it is not possible for an operator declared in a derived class to hide an operator declared in a base class. Thus, the new modifier is never required, and therefore never permitted, in an operator declaration.

Above quote from c# Language specification


It does, Compiler checks to see any operator overloading defined in inheritance hierarchy. If found it uses that

Consider the following code

class Person
{
    public int Age;
    public static int operator +(Person p, Person p2)
    {
        return p.Age + p2.Age;
    }
}
class Agent : Person
{

}
static void Main()
{
    Person p = new Person { Age = 23 };
    Agent agent = new Agent { Age = 25 };

    int res = p + agent;//Result 48
    Console.WriteLine("Result is "+ res);
}

In your case compiler found ++ operator and tries to use it, but the problem is with return type. It returns base type, so it won't work. It can't be assigned to more derived type.

Here is the Demo

17 Comments

Does Agent inherit the custom operator?
No, the operator is not inherited. The operands are converted.
@HenkHolterman It is inherited. All operators except(=) are inherited. Source check the 9th bullet
@BrahimBoulkriat Yes it is inherits. Check it out here
@SriramSakthivel This is a link about operator overloading in C++.
|
0

The ugly/pretty but not so generic solution:

class Agent : Person 
{
    public static Agent operator ++(Agent p)
    {
        p.Age++;
        return p;
    }
}

Comments

0

For this particular case, you could go with something like

class Person
{
    public int Age;
    public static T IncrementAge<T>(T p) where T : Person
    {
        p.Age++;
        return p;
    }
}

Unfortunatelly, the following doesn't work:

    public static T operator ++<T>(T p) where T : Person
    {
        p.Age++;
        return p;
    }

The straight forward way would probably rather be this one, though:

    public void IncrementAge()
    {
        Age++;
    }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.