C#:函数中的'out'out'参数是对象属性/变量吗?

时间:2010-08-06 08:23:48

标签: c# out-parameters

C#:函数中的'out'out'参数是对象属性/变量吗?

例如:

我可以按如下方式调用函数:

someFunction(x, y, out myObject.MyProperty1)

5 个答案:

答案 0 :(得分:6)

属性是[一对get和set]方法,它们具有可爱的语法,用于调用它们使它们看起来像字段。

Out参数可以是对字段或基于堆栈的“字段”(即本地)的引用。

这种差距的弥合通常不是由语言解决的(并且肯定不是由CLR和IL模型直接解决)。 (关于VB技巧参考的@Heinzi +1)

答案 1 :(得分:4)

不,您不能将属性用作C#中的refout参数,因为CLR不支持此功能。传递实例变量应该可以正常工作。

作为旁注,VB.NET允许传递属性并使用一种名为“copy back ByRef”的技术,如this MSDN blog entry中所述。

答案 2 :(得分:4)

你不能用C#做到这一点 你可以使用VB.Net,但我认为这是个坏主意。下面的代码和输出显示它是如何做到的,并显示为什么我认为这是一个坏主意,我希望VB.net也不允许这样做

Public Class MySimpleClass
    Private _privateInt As Integer
    Public PublicInt As Integer

    Public Property PrivateInt() As Integer
        Get
            Return _privateInt
        End Get
        Set(ByVal value As Integer)
            _privateInt = value
        End Set
    End Property

    Public Sub MyNotifier()
        Console.WriteLine("PublicInt {0} : PrivateInt {1} : Values are not the same", PublicInt, PrivateInt)
    End Sub

End Class

现在从子主程序中调用它,如此

Sub Main()
    Dim sampleClass As New MySimpleClass
    IterateAndUpdate(sampleClass.PrivateInt, sampleClass.PublicInt, AddressOf sampleClass.MyNotifier)

    Console.WriteLine("Private {0} : Public {0} : values are the same ", sampleClass.PrivateInt, sampleClass.PublicInt)
    Console.ReadKey()
End Sub

Sub IterateAndUpdate(ByRef anInt As Integer, ByRef anOtherInt As Integer, ByVal notifier As Action)
    For i As Integer = 1 To 9
        anInt = i
        anOtherInt = i
        notifier()
    Next
End Sub

此输出

  

PublicInt 1:PrivateInt 0:值不一样
  PublicInt 2:PrivateInt 0:值不一样
  PublicInt 3:PrivateInt 0:值不一样
  PublicInt 4:PrivateInt 0:值不一样
  PublicInt 5:PrivateInt 0:值不一样
  PublicInt 6:PrivateInt 0:值不一样
  PublicInt 7:PrivateInt 0:值不一样
  PublicInt 8:PrivateInt 0:值不一样
  PublicInt 9:PrivateInt 0:值不一样
  私人9:公众9:价值观相同

您可以看到PublicInt成员在传递ByRef时立即在sampleClass上更新,将PrivateInt公开为属性仅在IterateAndUpdate方法结束后更新。

因此,您会从完全相同的调用约定中获得明显不同的行为,这取决于您实现传递的项目的方式(看起来对IterateAndUpdate的调用并不明显。
隐藏错误的可能性,或者微小的变化改变了预期的行为,这足以让我希望这个“功能”不存在。

在我看来,这不正常,因此它应该是
a)固定,这将为编译器团队付出相当大的努力,并可能引入重大变化 或
b)根本不工作

答案 3 :(得分:3)

传递给out参数的参数不能是属性。如果您尝试编译代码,则会出现编译错误。

  

属性,索引器或动态成员访问权限不能作为out或ref参数传递

原因是属性实际上不是字段(它可能有一个支持字段,但可能没有)。这是两种称为get_Fooset_Foo的方法。有关为什么不起作用的详细说明,请参阅c# property and ref parameter, why no sugar?

给出编译错误的示例代码:

class Program
{
    public int Foo { get; set; }
    public void Bar(out int x)
    {
        x = 5;
    }
    void Run()
    {
        Bar(out Foo); // compile error 
    }
    static void Main()
    {
        new Program().Run();
    }
}

答案 4 :(得分:0)

您可以将out参数与字段(或已经说明的本地人)一起使用。