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

问题描述:

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

如:

我可以调用一个函数如下:

someFunction(x, y, out myObject.MyProperty1) 
+10

编译器说什么? – flq 2010-08-06 08:25:48

+1

@Frank:如果我知道,为什么我会问这个问题? – CJ7 2010-08-13 02:15:26

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

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

弥合这种差距一般不会由语言来解决(并且绝对不是直接由CLR和IL模型来解决)。 (@Heinzi上的+1用于VB欺骗引用)

+1

对于-1的基本原理将不胜感激(除了@Mark Byers的回答自从它初始发布以来已经包含了这个角度的事实?) – 2010-08-06 14:58:54

+1

@Craig Johnston:我赞扬你看到通过答案的迷雾和辩论你引起的看似简单的问题! – 2010-08-13 07:30:30

+0

+1:为了恰当地确定,您确实需要为每个属性捕获一对关闭。在那一刻'ref int i'会隐藏一些相关的代码。 。 。但只有当一个属性通过。取消引用int和围绕和使用闭包对之间的区别很大。附:我无法忍受没有评论的低估。 – 2010-08-13 12:45:23

传递给输出参数不能是属性的参数。如果你尝试编译你的代码,你会得到一个编译错误。

A property, indexer or dynamic member access may not be passed as an out or ref parameter

原因是一个属性实际上不是字段(它可能有一个后台字段,但它可能没有)。它有两种方法,称为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(); 
    } 
} 

不,你不能使用财产在C#中的refout参数,因为CLR不支持此。通过实例变量应该可以正常工作。

作为一个附注,VB.NET允许传递属性并使用称为“copyback ByRef”的技术,如this MSDN blog entry中所述。

+2

+1:我强烈建议不要在VB.Net中传递属性byref,可能会产生令人惊讶的副作用,如果像C#一样不受支持,效果会更好。 – 2010-08-06 08:36:51

+2

@Binary:你有没有这方面的证据/参考资料? – CJ7 2010-08-06 08:41:27

+0

@Craig:在下面添加了我自己的“答案”,用VB代码示例显示了我的意思http://*.com/questions/3422078/c-can-out-parameters-in-functions-be-object- properties-variables/3424123#3424123 – 2010-08-06 13:23:06

您可以使用out参数与字段(或本地人,如上所述)。

你不能用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 : Values are not the same
PublicInt 2 : PrivateInt 0 : Values are not the same
PublicInt 3 : PrivateInt 0 : Values are not the same
PublicInt 4 : PrivateInt 0 : Values are not the same
PublicInt 5 : PrivateInt 0 : Values are not the same
PublicInt 6 : PrivateInt 0 : Values are not the same
PublicInt 7 : PrivateInt 0 : Values are not the same
PublicInt 8 : PrivateInt 0 : Values are not the same
PublicInt 9 : PrivateInt 0 : Values are not the same
Private 9 : Public 9 : values are the same

你可以看到,当传递ByRefPublicInt部件上sampleClass立即更新,把作为属性的仅在IterateAndUpdate方法结束后更新。

因此,你完全一样的调用约定得到明显不同的行为,这要看你已经实现了该项目已通过(这是不是在所有明显的看调用IterateAndUpdate
的潜力隐藏的错误,或者有小的变化而改变预期的行为是足以让我想这个“功能”是不存在的。

在我看来,这并不正常工作,因此它应该不包括
一)固定的,这编译团队需要付出相当大的努力,并且可能会引入重大更改

b)根本不工作

+1

+1,有趣的分析。 – Heinzi 2010-08-06 21:38:07