C#自定义一元运算符重载

Bra*_*iat 2 c# operator-overloading

C#类是否从基类继承自定义运算符?我正在尝试以下代码:

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);

}
Run Code Online (Sandbox Code Playgroud)

编译器告诉我,他无法显式地从Person转换为Agent.

我试过了 :

Agent agent = new Agent();
Person person = agent ++
Run Code Online (Sandbox Code Playgroud)

但是会出现相同的编译器消息.

Run*_* FS 6

您遇到的问题不是基于运算符是否继承,而是由于运算符的返回类型.

但是,在分配运算符的情况下,运算符的返回类型会出现问题

这个表达x++方式很简单

x = x + 1
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你正在返回Person并尝试将其分配给Agent.写出来的

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

您只能分配更通用的类型.因此,分配Agent一个Person将工作,这就是为什么编译器将允许返回类型是实现类型的特化(如下所示).

你可以通过一些泛型技巧来完成你正在寻找的东西

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> { }
Run Code Online (Sandbox Code Playgroud)

上面的运算符构造了一个新对象,对我而言,该对象与++运算符的约定内联,但如果您希望可以使用强制转换,则还需要默认构造函数.

public static T operator ++(Person<T> p)
{
    p.Age++;
    return (T)p;
}
Run Code Online (Sandbox Code Playgroud)

是否继承运算符取决于您如何定义继承.

C#规范以与CLI规范不同的方式使用"继承" .C#规范使用继承的方式是在运算符和静态方法的上下文中与CLI规范不兼容(即C#规范与CLI规范相矛盾,因此运行的C#平台不支持规范)

为了说明我的钱为什么"运算符不是继承的",它们是静态方法的语法糖.

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

这是静态方法的实现.根据CLI规范,静态方法不会被继承:

派生对象类型继承其基础对象类型的所有实例和虚方法.它不继承构造函数或静态方法.

下面是++运营商的实施

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

这两种实现的IL都是相同的