I don't understand when an output parameter should be used, I personally wrap the result in a new type if I need to return more than one type, I find that a lot easier to work with than out.
我不明白何时应该使用输出参数,如果我需要返回多个类型,我个人将结果包装成新类型,我发现使用它比使用更容易。
I have seen method like this,
我见过这样的方法,
public void Do(int arg1, int arg2, out int result)
are there any cases where that actually makes sense?
有没有真正有意义的案例?
how about TryParse
, why not return a ParseResult
type? or in the newer framework return a null-able type?
TryParse怎么样,为什么不返回ParseResult类型?或者在较新的框架中返回一个null-able类型?
10 个解决方案
#1
25
Out is good when you have a TryNNN
function and it's clear that the out-parameter will always be set even if the function does not succeed. This allows you rely on the fact that the local variable you declare will be set rather than having to place checks later in your code against null. (A comment below indicates that the parameter could be set to null
, so you may want to verify the documentation for the function you're calling to be sure if this is the case or not.) It makes the code a little clearer and easier to read. Another case is when you need to return some data and a status on the condition of the method like:
当你有一个TryNNN函数时,out很好,很明显即使函数没有成功,也会设置out参数。这允许您依赖于您声明的局部变量将被设置的事实,而不是必须在稍后的代码中对null进行检查。 (下面的注释表明该参数可以设置为null,因此您可能需要验证您正在调用的函数的文档,以确定是否是这种情况。)它使代码更清晰,更容易读书。另一种情况是,当您需要返回一些数据和状态时,如下所示:
public bool DoSomething(int arg1, out string result);
In this case the return can indicate if the function succeeded and the result is stored in the out parameter. Admittedly, this example is contrived because you can design a way where the function simply returns a string
, but you get the idea.
在这种情况下,返回可以指示函数是否成功,结果是否存储在out参数中。不可否认,这个例子是设计的,因为你可以设计一种方法,函数只返回一个字符串,但你明白了。
A disadvantage is that you have to declare a local variable to use them:
缺点是你必须声明一个局部变量来使用它们:
string result;
if (DoSomething(5, out result))
UpdateWithResult(result);
Instead of:
代替:
UpdateWithResult(DoSomething(5));
However, that may not even be a disadvantage, it depends on the design you're going for. In the case of DateTime, both means (Parse and TryParse) are provided.
然而,这可能不是一个缺点,它取决于你想要的设计。在DateTime的情况下,提供了两种方法(Parse和TryParse)。
#2
5
Well as with most things it depends. Let us look at the options
这与大多数事情有关。让我们看一下选项
- you could return whatever you want as the return value of the function
- 你可以返回你想要的任何东西作为函数的返回值
- if you want to return multiple values or the function already has a return value, you can either use out params or create a new composite type that exposes all these values as properties
- 如果要返回多个值或函数已有返回值,可以使用params或创建一个新的复合类型,将所有这些值公开为属性
In the case of TryParse, using an out param is efficient - you dont have to create a new type which would be 16B of overhead (on 32b machines) or incur the perf cost of having them garbage collected post the call. TryParse could be called from within a loop for instance - so out params rule here.
For functions that would not be called within a loop (i.e. performance is not a major concern), returning a single composite object might be 'cleaner' (subjective to the beholder). Now with anonymous types and Dynamic typing , it might become even easier.
在TryParse的情况下,使用out param是有效的 - 你不必创建一个新的类型,它将是16B的开销(在32b机器上)或者在调用后产生垃圾收集的成本。例如,可以在循环内调用TryParse - 所以在这里输出params规则。对于不在循环内调用的函数(即性能不是主要问题),返回单个复合对象可能是“更清晰”(对于旁观者来说是主观的)。现在使用匿名类型和动态类型,它可能变得更加容易。
Note:
注意:
-
out
params have some rules that need to be followed i.e. the compiler will ensure that the function does initialize the value before it exits. So TryParse has to set the out param to some value even if parse operation failed - out params有一些需要遵循的规则,即编译器将确保函数在退出之前初始化值。因此,即使解析操作失败,TryParse也必须将out参数设置为某个值
- The TryXXX pattern is a good example of when to use out params - Int32.TryParse was introduced coz people complained of the perf hit of catching exceptions to know if parse failed. Also the most likely thing you'd do in case parse succeeded, is to obtain the parsed value - using an out param means you do not have to make another method call to Parse
- TryXXX模式是何时使用params的一个很好的例子 - Int32.TryParse被引入了coz人们抱怨捕获异常以确定解析是否失败。在解析成功的情况下你最有可能做的就是获得解析后的值 - 使用out参数意味着你不必再对Parse进行另一个方法调用
#3
3
I think out is useful for situations where you need to return both a boolean and a value, like TryParse, but it would be nice if the compiler would allow something like this:
我认为out对于需要返回布尔值和值的情况很有用,比如TryParse,但如果编译器允许这样的话会很好:
bool isValid = int.TryParse("100", out int result = 0);
#4
2
Definitely, out parameters are intended to be used when you have a method that needs to return more than one value, in the example you posted:
当然,如果您有一个需要返回多个值的方法,那么在您发布的示例中,将使用out参数:
public void Do(int arg1, int arg2, out int result)
It doesn't makes much sense to use an out parameter, since you are only returning one value, and that method could be used better if you remove the out parameter and put a int return value:
使用out参数没有多大意义,因为您只返回一个值,如果删除out参数并输入int返回值,则可以更好地使用该方法:
public int Do(int arg1, int arg2)
There are some good things about out parameters:
关于out参数有一些好处:
- Output parameters are initially considered unassigned.
- Every out parameter must be definitely assigned before the method returns, your code will not compile if you miss an assignment.
- 在方法返回之前必须明确赋值每个out参数,如果错过了赋值,则代码将无法编译。
- 输出参数最初被视为未分配。在方法返回之前必须明确赋值每个out参数,如果错过了赋值,则代码将无法编译。
In conclusion, I basically try use out params in my private API to avoid creating separate types to wrap multiple return values, and on my public API, I only use them on methods that match with the TryParse pattern.
总之,我基本上尝试在我的私有API中使用params以避免创建单独的类型来包装多个返回值,而在我的公共API上,我只在与TryParse模式匹配的方法上使用它们。
#5
1
Years late with an answer, I know. out (and ref as well) is also really useful if you do not wish your method do instantiate a new object to return. This is very relevant in high-performance systems where you want to achieve sub microsecond performance for your method. instantiating is relatively expensive seen from a memory access perspective.
我知道,答案已经很晚了几年。 out(和ref)也非常有用,如果你不希望你的方法实例化一个新对象返回。这在您希望为您的方法实现亚微秒性能的高性能系统中非常相关。从内存访问的角度来看,实例化是相对昂贵的。
#6
0
Creating a type just for returning values sounds little painful to me :-) First i will have to create a type for returning the value then in the calling method i have assign the value from the returned type to the actual variable that needs it.
创建一个只返回值的类型对我来说听起来很痛苦:-)首先,我必须创建一个返回值的类型然后在调用方法中我已经将返回类型的值赋给需要它的实际变量。
Out parameters are simipler to use.
输出参数比较简单。
#7
0
Yes, it does make sense. Take this for example.
是的,它确实有意义。以此为例。
String strNum = "-1";
Int32 outNum;
if (Int32.TryParse(strNum, out outNum)) {
// success
}
else {
// fail
}
What could you return if the operation failed in a normal function with a return value? You most certainly could not return -1 to represent a fail, because then there would be no differentiation between the fail-return value and the actual value that was being parsed to begin with. This is why we return a Boolean value to see if it succeeded, and if it did then we have our "return" value safely assigned already.
如果操作在具有返回值的正常函数中失败,您会返回什么?你当然不能返回-1来表示失败,因为那时失败返回值和正在解析的实际值之间没有区别。这就是为什么我们返回一个布尔值来查看它是否成功,如果它成功,那么我们已经安全地分配了我们的“返回”值。
#8
0
It does annoy me that I can't pass in null to the out parameter for the TryParse functions.
它让我很烦恼,我无法将null传递给TryParse函数的out参数。
Still, I prefer it in some cases to returning a new type with two pieces of data. Especially when they're unrelated for the most part or one piece is only needed for a single operation a moment after. When I do need to save the resulting value of a TryParse function I really like having an out parameter rather than some random ResultAndValue class that I have to deal with.
不过,在某些情况下,我更喜欢使用两个数据返回一个新类型。特别是当他们大部分时间不相关或者一件事后只需要一次操作时。当我确实需要保存TryParse函数的结果值时,我真的很喜欢使用out参数而不是一些我必须处理的随机ResultAndValue类。
#9
0
If you always create a type, then you can end up with a lot of clutter in your application.
如果您总是创建一个类型,那么您的应用程序中可能会出现大量混乱。
As said here, one typical use case is a TrySomething
Method where you want to return a bool as an indicator for success and then the actual value. I also find that a little bit cleaner in an if-statement - all three options roughly have the same LOC anyway.
如上所述,一个典型的用例是TrySomething方法,您希望返回bool作为成功的指标,然后返回实际值。我还发现在if语句中有点干净 - 所有三个选项大致都具有相同的LOC。
int myoutvalue;
if(int.TryParse("213",out myoutvalue){
DoSomethingWith(myoutvalue);
}
vs.
ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
DoSomethingWith(myoutvalue.Value);
}
vs.
int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
DoSomethingWith(myoutvalue.Value);
}
As for the "Why not return a Nullable Type": TryParse exists since Framework 1.x, whereas Nullable Types came with 2.0 (As they require Generics). So why unneccessarily break compatibility or start introducing inconsistencies between TryParse on some types? You can always write your own extension Method to duplicate functionality already existing (See Eric Lipperts Post on an unrelated subject that includes some reasoning behind doing/not doing stuff)
至于“为什么不返回可以为Nullable的类型”:自Framework 1.x以来,TryParse存在,而Nullable Types带有2.0(因为它们需要Generics)。那么为什么不必要地破坏兼容性或开始在某些类型的TryParse之间引入不一致?您总是可以编写自己的扩展方法来复制已经存在的功能(请参阅Eric Lipperts Post上一篇不相关的主题,其中包括执行/不执行操作的一些原因)
Another use case is if you have to return multiple unrelated values, even though if you do that that should trigger an alarm that your method is possibly doing too much. On the other hand, if your Method is something like an expensive database or web service call and you want to cache the result, it may make sense to do that. Sure, you could create a type, but again, that means one more type in your application.
另一个用例是,如果你必须返回多个不相关的值,即使你这样做会触发警报,你的方法可能做得太多了。另一方面,如果您的Method类似于昂贵的数据库或Web服务调用,并且您想要缓存结果,那么这样做可能是有意义的。当然,您可以创建一个类型,但同样,这意味着您的应用程序中还有一种类型。
#10
0
I use out parameters sometimes for readability, when reading the method name is more important than whatever the output of the method is—particularly for methods that execute commands in addition to returning results.
我有时会使用参数来提高可读性,当读取方法名称比方法输出更重要时 - 特别是对于执行命令以及返回结果的方法。
StatusInfo a, b, c;
Initialize(out a);
Validate(a, out b);
Process(b, out c);
vs.
与
StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);
At least for me, I put a lot of emphasis on the first few characters of each line when I'm scanning. I can easily tell what's going on in the first example after acknowledging that some "StatusInfo" variables are declared. In the second example, the first thing I see is that a bunch of StatusInfo is retrieved. I have to scan a second time to see what kind of effects the methods may have.
至少对我来说,我在扫描时非常强调每行的前几个字符。在确认声明了一些“StatusInfo”变量之后,我可以轻松地告诉第一个例子中发生了什么。在第二个例子中,我看到的第一件事就是检索了一堆StatusInfo。我必须再次扫描一下,看看方法可能会产生什么样的影响。
#1
25
Out is good when you have a TryNNN
function and it's clear that the out-parameter will always be set even if the function does not succeed. This allows you rely on the fact that the local variable you declare will be set rather than having to place checks later in your code against null. (A comment below indicates that the parameter could be set to null
, so you may want to verify the documentation for the function you're calling to be sure if this is the case or not.) It makes the code a little clearer and easier to read. Another case is when you need to return some data and a status on the condition of the method like:
当你有一个TryNNN函数时,out很好,很明显即使函数没有成功,也会设置out参数。这允许您依赖于您声明的局部变量将被设置的事实,而不是必须在稍后的代码中对null进行检查。 (下面的注释表明该参数可以设置为null,因此您可能需要验证您正在调用的函数的文档,以确定是否是这种情况。)它使代码更清晰,更容易读书。另一种情况是,当您需要返回一些数据和状态时,如下所示:
public bool DoSomething(int arg1, out string result);
In this case the return can indicate if the function succeeded and the result is stored in the out parameter. Admittedly, this example is contrived because you can design a way where the function simply returns a string
, but you get the idea.
在这种情况下,返回可以指示函数是否成功,结果是否存储在out参数中。不可否认,这个例子是设计的,因为你可以设计一种方法,函数只返回一个字符串,但你明白了。
A disadvantage is that you have to declare a local variable to use them:
缺点是你必须声明一个局部变量来使用它们:
string result;
if (DoSomething(5, out result))
UpdateWithResult(result);
Instead of:
代替:
UpdateWithResult(DoSomething(5));
However, that may not even be a disadvantage, it depends on the design you're going for. In the case of DateTime, both means (Parse and TryParse) are provided.
然而,这可能不是一个缺点,它取决于你想要的设计。在DateTime的情况下,提供了两种方法(Parse和TryParse)。
#2
5
Well as with most things it depends. Let us look at the options
这与大多数事情有关。让我们看一下选项
- you could return whatever you want as the return value of the function
- 你可以返回你想要的任何东西作为函数的返回值
- if you want to return multiple values or the function already has a return value, you can either use out params or create a new composite type that exposes all these values as properties
- 如果要返回多个值或函数已有返回值,可以使用params或创建一个新的复合类型,将所有这些值公开为属性
In the case of TryParse, using an out param is efficient - you dont have to create a new type which would be 16B of overhead (on 32b machines) or incur the perf cost of having them garbage collected post the call. TryParse could be called from within a loop for instance - so out params rule here.
For functions that would not be called within a loop (i.e. performance is not a major concern), returning a single composite object might be 'cleaner' (subjective to the beholder). Now with anonymous types and Dynamic typing , it might become even easier.
在TryParse的情况下,使用out param是有效的 - 你不必创建一个新的类型,它将是16B的开销(在32b机器上)或者在调用后产生垃圾收集的成本。例如,可以在循环内调用TryParse - 所以在这里输出params规则。对于不在循环内调用的函数(即性能不是主要问题),返回单个复合对象可能是“更清晰”(对于旁观者来说是主观的)。现在使用匿名类型和动态类型,它可能变得更加容易。
Note:
注意:
-
out
params have some rules that need to be followed i.e. the compiler will ensure that the function does initialize the value before it exits. So TryParse has to set the out param to some value even if parse operation failed - out params有一些需要遵循的规则,即编译器将确保函数在退出之前初始化值。因此,即使解析操作失败,TryParse也必须将out参数设置为某个值
- The TryXXX pattern is a good example of when to use out params - Int32.TryParse was introduced coz people complained of the perf hit of catching exceptions to know if parse failed. Also the most likely thing you'd do in case parse succeeded, is to obtain the parsed value - using an out param means you do not have to make another method call to Parse
- TryXXX模式是何时使用params的一个很好的例子 - Int32.TryParse被引入了coz人们抱怨捕获异常以确定解析是否失败。在解析成功的情况下你最有可能做的就是获得解析后的值 - 使用out参数意味着你不必再对Parse进行另一个方法调用
#3
3
I think out is useful for situations where you need to return both a boolean and a value, like TryParse, but it would be nice if the compiler would allow something like this:
我认为out对于需要返回布尔值和值的情况很有用,比如TryParse,但如果编译器允许这样的话会很好:
bool isValid = int.TryParse("100", out int result = 0);
#4
2
Definitely, out parameters are intended to be used when you have a method that needs to return more than one value, in the example you posted:
当然,如果您有一个需要返回多个值的方法,那么在您发布的示例中,将使用out参数:
public void Do(int arg1, int arg2, out int result)
It doesn't makes much sense to use an out parameter, since you are only returning one value, and that method could be used better if you remove the out parameter and put a int return value:
使用out参数没有多大意义,因为您只返回一个值,如果删除out参数并输入int返回值,则可以更好地使用该方法:
public int Do(int arg1, int arg2)
There are some good things about out parameters:
关于out参数有一些好处:
- Output parameters are initially considered unassigned.
- Every out parameter must be definitely assigned before the method returns, your code will not compile if you miss an assignment.
- 在方法返回之前必须明确赋值每个out参数,如果错过了赋值,则代码将无法编译。
- 输出参数最初被视为未分配。在方法返回之前必须明确赋值每个out参数,如果错过了赋值,则代码将无法编译。
In conclusion, I basically try use out params in my private API to avoid creating separate types to wrap multiple return values, and on my public API, I only use them on methods that match with the TryParse pattern.
总之,我基本上尝试在我的私有API中使用params以避免创建单独的类型来包装多个返回值,而在我的公共API上,我只在与TryParse模式匹配的方法上使用它们。
#5
1
Years late with an answer, I know. out (and ref as well) is also really useful if you do not wish your method do instantiate a new object to return. This is very relevant in high-performance systems where you want to achieve sub microsecond performance for your method. instantiating is relatively expensive seen from a memory access perspective.
我知道,答案已经很晚了几年。 out(和ref)也非常有用,如果你不希望你的方法实例化一个新对象返回。这在您希望为您的方法实现亚微秒性能的高性能系统中非常相关。从内存访问的角度来看,实例化是相对昂贵的。
#6
0
Creating a type just for returning values sounds little painful to me :-) First i will have to create a type for returning the value then in the calling method i have assign the value from the returned type to the actual variable that needs it.
创建一个只返回值的类型对我来说听起来很痛苦:-)首先,我必须创建一个返回值的类型然后在调用方法中我已经将返回类型的值赋给需要它的实际变量。
Out parameters are simipler to use.
输出参数比较简单。
#7
0
Yes, it does make sense. Take this for example.
是的,它确实有意义。以此为例。
String strNum = "-1";
Int32 outNum;
if (Int32.TryParse(strNum, out outNum)) {
// success
}
else {
// fail
}
What could you return if the operation failed in a normal function with a return value? You most certainly could not return -1 to represent a fail, because then there would be no differentiation between the fail-return value and the actual value that was being parsed to begin with. This is why we return a Boolean value to see if it succeeded, and if it did then we have our "return" value safely assigned already.
如果操作在具有返回值的正常函数中失败,您会返回什么?你当然不能返回-1来表示失败,因为那时失败返回值和正在解析的实际值之间没有区别。这就是为什么我们返回一个布尔值来查看它是否成功,如果它成功,那么我们已经安全地分配了我们的“返回”值。
#8
0
It does annoy me that I can't pass in null to the out parameter for the TryParse functions.
它让我很烦恼,我无法将null传递给TryParse函数的out参数。
Still, I prefer it in some cases to returning a new type with two pieces of data. Especially when they're unrelated for the most part or one piece is only needed for a single operation a moment after. When I do need to save the resulting value of a TryParse function I really like having an out parameter rather than some random ResultAndValue class that I have to deal with.
不过,在某些情况下,我更喜欢使用两个数据返回一个新类型。特别是当他们大部分时间不相关或者一件事后只需要一次操作时。当我确实需要保存TryParse函数的结果值时,我真的很喜欢使用out参数而不是一些我必须处理的随机ResultAndValue类。
#9
0
If you always create a type, then you can end up with a lot of clutter in your application.
如果您总是创建一个类型,那么您的应用程序中可能会出现大量混乱。
As said here, one typical use case is a TrySomething
Method where you want to return a bool as an indicator for success and then the actual value. I also find that a little bit cleaner in an if-statement - all three options roughly have the same LOC anyway.
如上所述,一个典型的用例是TrySomething方法,您希望返回bool作为成功的指标,然后返回实际值。我还发现在if语句中有点干净 - 所有三个选项大致都具有相同的LOC。
int myoutvalue;
if(int.TryParse("213",out myoutvalue){
DoSomethingWith(myoutvalue);
}
vs.
ParseResult<int> myoutvalue = int.TryParse("213");
if ( myoutvalue.Success ) {
DoSomethingWith(myoutvalue.Value);
}
vs.
int? myoutvalue = int.TryParse("213");
if(myoutvalue.HasValue){
DoSomethingWith(myoutvalue.Value);
}
As for the "Why not return a Nullable Type": TryParse exists since Framework 1.x, whereas Nullable Types came with 2.0 (As they require Generics). So why unneccessarily break compatibility or start introducing inconsistencies between TryParse on some types? You can always write your own extension Method to duplicate functionality already existing (See Eric Lipperts Post on an unrelated subject that includes some reasoning behind doing/not doing stuff)
至于“为什么不返回可以为Nullable的类型”:自Framework 1.x以来,TryParse存在,而Nullable Types带有2.0(因为它们需要Generics)。那么为什么不必要地破坏兼容性或开始在某些类型的TryParse之间引入不一致?您总是可以编写自己的扩展方法来复制已经存在的功能(请参阅Eric Lipperts Post上一篇不相关的主题,其中包括执行/不执行操作的一些原因)
Another use case is if you have to return multiple unrelated values, even though if you do that that should trigger an alarm that your method is possibly doing too much. On the other hand, if your Method is something like an expensive database or web service call and you want to cache the result, it may make sense to do that. Sure, you could create a type, but again, that means one more type in your application.
另一个用例是,如果你必须返回多个不相关的值,即使你这样做会触发警报,你的方法可能做得太多了。另一方面,如果您的Method类似于昂贵的数据库或Web服务调用,并且您想要缓存结果,那么这样做可能是有意义的。当然,您可以创建一个类型,但同样,这意味着您的应用程序中还有一种类型。
#10
0
I use out parameters sometimes for readability, when reading the method name is more important than whatever the output of the method is—particularly for methods that execute commands in addition to returning results.
我有时会使用参数来提高可读性,当读取方法名称比方法输出更重要时 - 特别是对于执行命令以及返回结果的方法。
StatusInfo a, b, c;
Initialize(out a);
Validate(a, out b);
Process(b, out c);
vs.
与
StatusInfo a = Initialize();
StatusInfo b = Validate(a);
StatusInfo c = Process(b);
At least for me, I put a lot of emphasis on the first few characters of each line when I'm scanning. I can easily tell what's going on in the first example after acknowledging that some "StatusInfo" variables are declared. In the second example, the first thing I see is that a bunch of StatusInfo is retrieved. I have to scan a second time to see what kind of effects the methods may have.
至少对我来说,我在扫描时非常强调每行的前几个字符。在确认声明了一些“StatusInfo”变量之后,我可以轻松地告诉第一个例子中发生了什么。在第二个例子中,我看到的第一件事就是检索了一堆StatusInfo。我必须再次扫描一下,看看方法可能会产生什么样的影响。