可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Are there any principles to keep in mind when using out parameters? Or can I look at them as just a good way to let a method return multiple values?
What did the language designers have in mind when they were specifying the out parameter?
Edit after some thought:
As i'm thinking about it now, I would be inclined to say that excessive use of out parameters could be indicitive of a code-smell. If a method needs to return instances of more than 1 specific type it implies that the method has more than 1 concern, which is a violation of SRP.
回答1:
Personally, I am not too keen on out
parameters beyond the established TryParse
convention. I prefer to return an instance of a specific type that encapsulates the different parameters, as it makes the code much easier to read imo.
If you don't want to define specific types for this, you can use the Tuple type in the upcoming .NET framework. Tuples are basically a bunch of values wrapped in a type. They are used a lot in e.g. F#.
回答2:
Using out parameters at all is generally bad practice. It typically indicates a method that is doing more than one well defined thing. The only time I recommend using them is for Interop scenarios where they are sometimes necessary because of the signature of the API.
回答3:
The class design tools specifically say to "Avoid out parameters", with a long discussion for the rationale.
Unless there is a good reason to use an out parameter for a method, it is typically better to make a custom class or struct to hold your results. Using out parameters reduces the usability of an API.
回答4:
One important caveat to keep in mind is that prior to .NET 3.5 SP1, methods that take or return value types are never inlined. This could have large performance implications for small and frequently called methods, such as those of a vector math library.
This is one of the main reasons why the SlimDX vector math library provides overloads that use out parameters instead of return values; it serves as a potential micro-optimization.
回答5:
I use out parameters when I write static TryParse methods on my classes.
Just to keep in sync with the CLR.
Other than that, its probably a better idea to return a class that has what you need on it.
回答6:
While out
parameters have their use, before using one you should stop and think if you really need it. You may be able to come up with a simpler, cleaner implementation that does not require out
.
why-are-out-parameters-in-net-a-bad-idea has more information.
回答7:
I often use nullable types when returning value types plus an indicator of success rather than returning a bool and using an out parameter for the value type. I even wrap the TryParse method so that it returns a nullable.
Out parameters are bad also because they must use local variables or fields. You can't easily refactor your code to use properties.
It's almost always best to create a custom class/struct, use tuples or nullable types.
回答8:
I generally view out parameters as a "code smell", and will try to refactor to a different approach if I run into them. As someone has already pointed out, commonly the refactoring will be to create a new class that aggregates the values you were going to be returning via out params.
回答9:
There are two situations where I don't see a problem at all in using out
parameters, and these situation most often happen along with one another:
- When a method has to return more than one value;
- When used in private methods, specifically in imperative sub-routines with a lower level of abstraction.
Comments on the rationale:
- Sometimes you can have operations that change more than one state, so you might operate in a group of objects belonging to a single process with only one function call (might be more semantically meaningful);
- Since intra-class variables are supposed to have high cohesion, thus high coupling, I believe "it doesn't hurt" to have methods using
out
parameters. That's exactly the opposite for public functions you expect to find in APIs;
- In C#, out parameters seem to show up a lot in code derived from more procedural APIs ported to OO. Numerical and scientific routines are the best example I can find (alglib, AForge, etc.). This reinforces my idea that it is fine to resort for
out
for internal implementation details, that can be very procedural depending on the problem domain.
As an example of a semantically "atomic" operation that changes two related but independent variables, here goes some Python code and how I ported it to C# (in a private method):
Python:
p1, p2 = FindClosestPair(p, listOfValues)
C#:
Point3D p1, p2;
FindClosestPair(p, listOfValues, out p1, out p2);
I could not think of a more straightforward way of doing it (but I would love to know possible alternatives).
回答10:
Only the same as return values - ie. be careful of anything the called class will retain and use later. On the whole, I do prefer a wrapper object though; makes the calling code a bit more readable.