Because the -
operator for string manipulation does not have enough "semantic cohesion." Operators should only be overloaded when it is absolutely clear what the overload does with its operands, and string subtraction doesn't meet that bar.
Consequently, method calls are preferred:
public string Remove(string source, string toRemove)
public string Replace(string source, string oldValue, string newValue)
In the C# language, we use +
for string concatenation because the form
var result = string1 + string2 + string3;
instead of
var result = string.Concat(string1, string2, string3);
is convenient and arguably easier to read, even though a function call is probably more "correct," from a semantic standpoint.
The +
operator can really only mean one thing in this context. This isn't as true for -
, since the notion of subtracting strings is ambiguous (the function call Replace(source, oldValue, newValue)
with ""
as the newValue
parameter removes all doubt, and the function can be used to alter substrings, not just remove them).
The problem, of course, is that the operator overload is dependent on the types being passed to the operator, and if you pass a string where a number should have been, you may get a result you didn't expect. In addition, for many concatenations (i.e. in a loop), a StringBuilder
object is preferable, since each use of +
creates a brand new string, and performance can suffer. So the +
operator isn't even appropriate in all contexts.
There are operator overloads that have better semantic cohesiveness than the +
operator does for string concatenation. Here's one that adds two complex numbers:
public static Complex operator +(Complex c1, Complex c2)
{
return new Complex(c1.real + c2.real, c1.imaginary + c2.imaginary);
}
+
operator is overloaded with the two totally unrelated meanings “numeric addition” and “string concatenation”. Thankfully, some languages provide a separate concatenation operator such as.
(Perl5, PHP),~
(Perl6),&
(VB),++
(Haskell), …->
(think dereferencing member access in C, since virtual method calls necessarily involve pointer-like indirection). There is no law of language design that requires method calls/member access to use a.
operator, though it is an increasingly common convention. Did you know that Smalltalk has no method call operator? Simple juxtapositionobject method
is sufficient.