Os principais operadores aritméticos e de comparação podem ser adaptados para uso nas suas próprias classes e structs. Isso é conhecido como sobrecarga de operadores.
Este artigo é uma discussão completa sobre a sintaxe, assim como sobre quais operadores podem ser sobrecarregados e quais não podem.
A maioria dos operadores tem a forma:
static <return type> operaator <operator symbols>(<parameters>);
Os operadores de conversão têm a forma:
static (explicit|implicit) operator <cast-to-type>(<cast-from-type> <parameter name>);
Os operadores se comportam da mesma forma que os métodos estáticos.
Exemplos de sintaxe:
struct Point
{
decimal x;
decimal y;
public static bool operator ==(Point pt, Point ptOther)
{
return pt.x == ptOther.x && pt.y == ptOther.y;
}
public static bool operator !=(Point pt, Point ptOther)
{
return !(pt == ptOther);
}
public static Point operator *(Point pt, decimal scale)
{
var ptNew = new Point();
ptNew.x = pt.x * scale;
ptNew.y = pt.y * scale;
return ptNew;
}
public static implicit operator Point((decimal x, decimal y) xy)
{
var pt = new Point();
pt.x = xy.x;
pt.y = xy.y;
return pt;
}
public static explicit operator (decimal x, decimal y)(Point pt)
{
return (pt.x, pt.y);
}
}
Muitas vezes é produtivo implementar um método Equals() e chamá-lo a partir do operador ==. Da mesma forma, para comparações, você pode implementar a interface IComparable. Nos dois casos, você mata dois coelhos com uma cajadada só.
Você deve observar que não é possível criar operadores a partir de símbolos que não fazem parte do conjunto padrão de operadores. Você só pode usar símbolos existentes para aquelas operações em que a documentação especifica que eles podem ser sobrecarregados. Os operadores que podem ser sobrecarregados estão listados aqui.
Repare que a ordem dos parâmetros é importante quando eles diferem em tipo. No código de exemplo acima, pt * 10m é uma expressão válida, enquanto 10m * pt não compila.
Esta documentação de sobrecarga de operadores detalha a sintaxe.