为什么在c#中使用out关键字而不是赋值?

为什么在c#中使用out关键字而不是赋值?,c#,language-design,C#,Language Design,在深入阅读了C#中关于它的部分之后,我一直在研究C#中的out关键字。我似乎找不到一个例子来说明为什么在分配return语句的值时需要关键字。例如: public void Function1(int input, out int output) { output = input * 5; } public int Function2(int input) { return input * 5; } ... int i; int j; Function1(5, out i)

在深入阅读了C#中关于它的部分之后,我一直在研究C#中的
out
关键字。我似乎找不到一个例子来说明为什么在分配return语句的值时需要关键字。例如:

public void Function1(int input, out int output)
{
    output = input * 5;
}

public int Function2(int input)
{
    return input * 5;
}

...
int i;
int j;

Function1(5, out i);
j = Function2(5);

现在i和j都具有相同的值。这仅仅是因为能够在没有
=
符号的情况下进行初始化的方便,还是因为我没有看到其他派生的值?我看到过一些类似的答案,提到它将初始化的责任转移给了被调用方。但是所有这些额外的内容,而不是仅仅分配一个返回值而没有一个无效的方法签名?

通常用于返回其他内容的方法,但是您仍然需要从该方法中获取不同的值

一个很好的例子是
Int32.TryParse(input,out myVar)
如果成功则返回true,否则返回false。您可以通过out参数获得转换后的int

int myOutVar;

if (Int32.TryParse("2", out myOutVar))
{
   //do something with the int
}else{
    //Parsing failed, show a message
}

例如,
Int32.TryParse
如果正确解析并使用out参数更改值,则返回布尔值。如果解析的值是
0
,并且返回
true
,则表示发送到解析的值是
0
。如果返回
false
,则解析器失败。

其中一些是为了清楚起见。以TryParse()方法为例,如

Int32.TryParse(“3”,out myInt)

这将返回一个bool,指示字符串是否能够被解析为int。 如果你有

Int32.TryParse("3", myInt);
打电话时会发生什么?myInt是否已分配?TryParse是否返回int


这不是很明显。但是如果我有一个
out
参数,那么我知道该值正在被赋值,并且返回值是另一个值。

不幸的是,我们无法在C#中执行以下操作:

我们用Python或其他语言所做的事情。我们克服了这一点

我相信F#已经用元组克服了这一点


PS:从函数返回多个值可能并不总是好的。小类型在大多数情况下都很好-

C#中的
out/ref
关键字只能在需要返回多个值时使用。即使这样,您应该首先考虑使用容器类型(例如<代码> tuple < /COD>)返回多个值,然后返回到“代码> out /REF”。无论何时,只要返回一个值,它就应该被返回

基本上您可以执行以下操作(我的数据库读取)

if(ReadSingle(cmd,out用户))
Insert(cacheId,user,null,
DateTime.MaxValue,TimeSpan.FromMinutes(3));
或者你做一些类似的事情:

user = ReadSingle<UserRecord>(cmd);
if(null != user)
   // Cache.Insert ...
user=ReadSingle(cmd);
if(null!=用户)
//缓存。插入。。。

使用布尔结果(即从数据库中读取记录)并通过
out
关键字将实际记录输入变量,可以稍微简化代码。

很多时候,使用
out
可以帮助您稍微提高性能

考虑
IDictionary
上的
TryGetValue
方法(假设myDictionary是一个
IDictionary
),而不是这样做:

string value = String.Empty;
if (myDictionary.ContainsKey("foo"))
{
  value = myDictionary["foo"];
}
ContainsKey
和索引器都需要在字典中查找键,但您可以通过以下步骤避免在正数情况下重复查找:

string value;
if (!myDictionary.TryGetValue("foo", out value))
{
  value = String.Empty;
}

依我看,这是使用
out
参数的正当理由。

换句话说,
out
用于返回多个值,而无需构建单独的对象来保存它们,这更高效,有时更方便。它也更具可读性。在Int32.TryParse的情况下,返回要转换的int是没有意义的,因为您无法确定转换是否失败。返回转换通过的true或false(可读性更强)更有意义,如果是,则获取转换后的int。我明白这意味着什么,我想我只是在阵营中,最好用异常处理结果…异常会完全释放调用堆栈,效率不高。这是一种更有效的方法。避免对try/catch块执行逻辑是一种很好的做法。@Xaisoft:虽然有些人喜欢让TryXX方法返回“ok”布尔值并将结果存储在“out”参数中,但我建议在返回结果时对布尔值使用“out”参数可能更干净。除此之外,(1)泛型接口中的函数返回类型支持协方差,但“out”参数不能;(2) 通常说“Boolean ok;var whatever=something.TryXXX(ok);if(ok)useValue(whatever);”比“whateverType whatever;if(TryXXX(whatever))useValue(whatever)更好;我觉得这有点有趣,几乎每个人都给出了一个完全相同的例子,这个例子有一个与参数无关的问题……在阅读了最初的答案后,这正是我所想的。非常有趣的是,没有任何资源(包括这本书)换句话说。本质上,这是一种允许多个返回值而不必将它们打包到传输对象中的方法?这会比仅仅抛出一个异常有好处吗?如果你试图解析一个int,但它失败了,因为它是一个字符串,你不应该负责处理它。我发现错误检测和更正与if/else语句相比,将section放在try-catch语句块中似乎更好。@这取决于无效格式是否为例外情况(在这种情况下,引发异常是正确的),然后您应该使用int.Parse,但在您可能期望无效格式的情况下(例如用户输入)你应该使用int。TryParse@Matt正如符文所说,这取决于具体情况。但无论如何。TryParse()的意图并不完全清楚。它几乎就像你看到的那些“bool”枚举,有人有False=0,True=1,Unknown=2伟大的例子。我发现
string value = String.Empty;
if (myDictionary.ContainsKey("foo"))
{
  value = myDictionary["foo"];
}
string value;
if (!myDictionary.TryGetValue("foo", out value))
{
  value = String.Empty;
}