There's another potential answer here, and I think akalenuk hinted at it. Use a maybe monad or some other similar, option type.
For example C#/.NET has
Nullable<T>, which isn't the same but is pretty close, but restricted to
Nullable<int> it should be enough.
public static Nullable<int> toInt(string s)
int i = 0;
if (int.TryParse(s, out I))
return new Nullable<int>(i);
return new Nullable<int>();
Also remember, that the transformation toInt is not 1 to 1 and invertible. You are transforming from a large set, the set of all possible strings, to the set of all possible integers (bounded by your types... which is relevant, but not that much). So it's not necessary, or even sensible to assume that toString is the inverse of toInt. The case where toInt(s).HasValue == false covers the case (set of all strings) - (set of all number strings)
However, we're not done.
Is this actually the general case? If so then what about number strings for which the value is too large to fit into an integer? Clearly, it's still a number. If it's not the general case then does your use case bound the set of output values within the range of an integer? If so, then you're done.
... if not, then we have to consider whether we need another type (Double? BigInteger?) BigInteger seems like it might fit the general case, still yet bounded by memory (OutOfMemoryException is possible).
In the end, if we're trying to shoot for something as general as possible, I'd go with:
public static Nullable<BigInteger> toInt(string s)
BigInteger bi = new BigInteger();
if (BigInteger.TryParse(s, out bi))
return new Nullable<BigInteger>(bi);
return new Nullable<BigInteger>();
Now, for the big sex... let's do it functionally (F# + options):
let toInt s =
match BigInteger.TryParse s with
| (true, parsed) -> Some parsed
| (false, _) -> None