I always use exclusive or (Xor) rather than addition, because it doesn't have a tendency to get numbers anywhere (like toward large values). So I would say that
protected override int GetHashCode()
{ return str1.GetHashCode() ^ str2.GetHashCode() ^ str3.GetHashCode(); }
is a better implementation.
You could also try a variation on it, like
protected override int GetHashCode()
{
unchecked
{
return (str1.GetHashCode() * 1369) ^
(str2.GetHashCode() * 37) ^ str3.GetHashCode();
}
}
if you want to make sure that switching the values of the strings gives a different result. There's all sorts of methods that can be used for hashing (e.g. universal hashing) so just do a search for hashing methods if that's what you're looking for.