inout参数有很好的用途吗?

时间:2009-02-27 20:29:29

标签: .net calling-convention

是否可以很好地使用inout(参见.NET中的C#,byref(如输出参数)参数)? 我觉得参数用作输入和返回值引起的混乱比out参数的数量增加,或返回数组或返回自定义类更糟糕。

9 个答案:

答案 0 :(得分:6)

我遇到的最常见的用途(仍然不常见,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();
}

答案 1 :(得分:5)

我主要使用它来适应遗留代码。=(com interop)。

我也倾向于在需要高效的代码中使用它并表明成功:

bool PerformSomeReadOperation(SomeInput obj, ref int defaultedOutput) { }

其中返回值是成功或失败的概念,或者可能是错误代码,而defaultedOutput是带有默认值的值。

您是否知道有no real difference between out and ref(至少就CLR而言)?

答案 2 :(得分:0)

当您可能进行一系列修改同一变量的调用时。

在C#这样的基于指针的语言中并没有发生太多事情,因为你可以将一个对象作为'in'参数传递,并且被调用的函数可以调用它的方法来根据需要修改它。

答案 3 :(得分:0)

在极少数情况下,它可能很有用,主要是出于性能原因。

在大多数情况下,它可以,并且在我看来应该通过返回数组或自定义类来避免。

答案 4 :(得分:0)

Ref和out参数传递模式用于允许方法更改方法调用者传入的变量。

每个参数传递模式(ref和out)旨在满足不同的编程需求。

需要输出参数的方法的调用者需要分配给在调用之前作为out参数传递的变量;但是,该方法需要在返回之前分配给out参数。

考虑 out 参数的一种方法是它们就像方法的其他返回值。当方法返回多个值时,它们很方便。

不要将引用传递的概念与引用类型的概念混淆。

这两个概念无关;一个方法参数可以通过ref修改,无论它是值类型还是引用类型,当通过引用传递时,没有值类型的装箱。

答案 5 :(得分:0)

我在图形例程中使用了值类型参数,在垂直布局中将文本打印到GDI窗口。 inout参数跟踪当前的Y位置:

WriteString("hello", ref y);

而不是

y += WriteString("hello", y);

答案 6 :(得分:0)

Out适用于需要多个返回值的简单情况。通过这种方式,您不会被ref可能导致的“它是一个参数/它是一个返回值”所迷惑。

public void GetStockQuote(
  string stock, 
  out double lastTrade, 
  out DateTime tradeTime, 
  out double change, 
  out double open)
{
  //perform stock magic here
}

答案 7 :(得分:0)

当我想修改一个值并认为包装类过度时,我会使用它。

例如

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函数可能会消耗多行。因此,他们负责正确更新索引变量。

答案 8 :(得分:0)

你真的回答了你自己的问题。

如果通过参数传入和传出数据是有意义的 - 即。如果方法需要知道当前值并且还希望更新它(或者,在引用类型的情况下,替换它),那么ref是正确的。它不会经常发生,但是当它发生时,你知道要使用什么; - )