Sure you can - you can introduce a new overload resolution rule that lets you treat trailing out params on a method as tuple members, so a method
TReturn Foo(T1 param1, out T2 param2)
can be called as if it were (TReturn, T2) Foo(T1 param1)
You'd need a keyword to trigger this kind of overload resolution at the call site to ensure back compatibility - maybe you'd have to call (var x, var y) = out Foo(param);
or something. That way all that legacy library code gets a free upgrade to your new language feature.Since the C# team decided not to do that, you can actually implement a version of this at a library level, by static importing a family of generic methods like this:
Func<TParam, (T1, T2)> Tuplify<TParam,T1,T2>(Func<TParam, out T1, T2> outFunc) {...}
for every pattern of out params you want to convert, then you can just call (var x, var y) = Tuplify(Foo)(param);
You can't retro-fit multiple-returns (via Tuples) onto existing library functions, so for places where you're forced into using out parameters, this is a slight improvement.