You are basically supplying our own implimentations for these operators (=, -, !, ~, ++, --, true, false, *, /, %, &, |, ^, ==, !=)(the only difference is that if you overload << you have to overload >>)when used with specific parameter types. It's exactly as when you overload methods by supplying different parameters for methods with the same name.
For example:
public class AddClass1
{
public int val;
public static AddClass3 operator +(AddClass1 op1, AddClass1 op2)
{
AddClass1 returnVal = new AddClass1();
returnVal.val = op1.val + op2.val;
return returnVal;
}
}
In this case you can make a call like the following:
AddClass1 op3 = op1 + op2;