.NET 中的 inout(C# 中的 ref,vb.net 中的 byref(如 out 参数))参数有很好的用途吗?
我觉得一个参数既作为输入又作为返回值造成的混乱,比out参数的参数数量增加,或者返回数组或者返回自定义类更糟糕。
9 回答
我遇到的最常见的用途(仍然不是那么常见,IMO)是一种“修改现有对象,或者在必要时创建一个”。例如:
public void AppendToBuilder(ref StringBuilder builder)
{
if (builder == null)
{
builder = new StringBuilder();
}
builder.Append(/* whatever */);
}
StringBuilder
可能不是一个很好的例子,但这意味着您有时可以避免在不需要时创建对象:
public static string DoSomething(IEnumerable<Foo> foos)
{
// For an empty collection or where there aren't any
// frobulating foos, we don't need to create a builder
StringBuilder builder = null;
foreach (Foo foo in foos)
{
if (foo.Frobulates)
{
foo.AppendToBuilder(ref builder);
}
}
return builder == null ? null : builder.ToString();
}
我主要用它来适应遗留代码。=(com互操作)。
我也倾向于在需要高性能并表明成功的代码中使用它:
bool PerformSomeReadOperation(SomeInput obj, ref int defaultedOutput) { }
其中返回值是成功或失败的概念,或者可能是错误代码,而 defaultedOutput 是带有默认值的值。
您是否知道out 和 ref 之间没有真正的区别(至少就 CLR 而言)?
当您可能进行一系列修改同一变量的调用时。
但是,在 C# 等基于指针的语言中,这种情况不会发生太多,因为您可以将对象作为“in”参数传递,并且被调用的函数可以调用其方法来根据需要对其进行修改。
在极少数情况下,它可能很有用,主要是出于性能原因。
在大多数情况下,它可以并且在我看来应该通过返回您提到的数组或自定义类来避免。
ref 和 out 参数传递模式用于允许方法更改由方法调用者传入的变量。
每种参数传递模式(ref 和 out)都旨在适应不同的编程需求。
带有out 参数的方法的调用者不需要在调用之前分配作为 out 参数传递的变量;但是,该方法需要在返回之前分配给 out 参数。
一种考虑out参数的方法是,它们就像方法的附加返回值。当一个方法应该返回多个值时,它们很方便。
不要将通过引用传递的概念与引用类型的概念混淆。
这两个概念不相关;方法参数无论是值类型还是引用类型都可以被ref修改,通过引用传递时没有值类型的装箱。
我在图形例程中将它与值类型参数一起使用,该例程以垂直布局将文本打印到 GDI 窗口。inout 参数跟踪当前的 Y 位置:
WriteString("hello", ref y);
而不是
y += WriteString("hello", y);
Out 适用于需要多个返回值的简单情况。这样您就不ref
会对可能导致的“它是参数/它是返回值”感到困惑。
public void GetStockQuote(
string stock,
out double lastTrade,
out DateTime tradeTime,
out double change,
out double open)
{
//perform stock magic here
}
当我想修改一个值并认为包装类太过分时,我会使用它。
例如
if (line[index].StartsWith("X12"))
ParseX12(lines, ref index, builder); //eats 2 or 4 lines
else if (line[index].StartsWith("A27"))
ParseA27(lines, ref index, builder); //eats 1 line
else if (line[index].StartsWith("B16"))
ParseB16(lines, ref index, builder); //eats 1 to 3 lines
else
index++; //this line couldn't be parsed, skip to the next one
在这个例子中,Parse 函数可能会消耗不止一行。因此,他们负责正确更新索引变量。
你真的回答了你自己的问题。
如果通过参数传入和传出数据是有意义的 - 即。如果该方法需要知道当前值并且还需要更新它(或者,在引用类型的情况下,替换它),那么 ref 是正确的。它不会经常发生,但是当它发生时,您知道该使用什么;-)