C#:函数中的'out'参数可以是对象属性/变量吗?
C#:函数中的'out'参数是对象的属性/变量吗?C#:函数中的'out'参数可以是对象属性/变量吗?
如:
我可以调用一个函数如下:
someFunction(x, y, out myObject.MyProperty1)
属性是[一对get和set]方法,用一个可爱的语法来调用它们,使它们看起来像字段。
Out参数可以是对字段或基于堆栈的“字段”(即本地)的引用。
弥合这种差距一般不会由语言来解决(并且绝对不是直接由CLR和IL模型来解决)。 (@Heinzi上的+1用于VB欺骗引用)
对于-1的基本原理将不胜感激(除了@Mark Byers的回答自从它初始发布以来已经包含了这个角度的事实?) – 2010-08-06 14:58:54
@Craig Johnston:我赞扬你看到通过答案的迷雾和辩论你引起的看似简单的问题! – 2010-08-13 07:30:30
+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_Foo
和set_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#中的ref
或out
参数,因为CLR不支持此。通过实例变量应该可以正常工作。
作为一个附注,VB.NET允许传递属性并使用称为“copyback ByRef”的技术,如this MSDN blog entry中所述。
+1:我强烈建议不要在VB.Net中传递属性byref,可能会产生令人惊讶的副作用,如果像C#一样不受支持,效果会更好。 – 2010-08-06 08:36:51
@Binary:你有没有这方面的证据/参考资料? – CJ7 2010-08-06 08:41:27
@Craig:在下面添加了我自己的“答案”,用VB代码示例显示了我的意思http://stackoverflow.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
你可以看到,当传递ByRef
的PublicInt
部件上sampleClass立即更新,把作为属性的仅在IterateAndUpdate
方法结束后更新。
因此,你完全一样的调用约定得到明显不同的行为,这要看你已经实现了该项目已通过(这是不是在所有明显的看调用IterateAndUpdate
。
的潜力隐藏的错误,或者有小的变化而改变预期的行为是足以让我想这个“功能”是不存在的。
在我看来,这并不正常工作,因此它应该不包括
一)固定的,这编译团队需要付出相当大的努力,并且可能会引入重大更改
或
b)根本不工作
+1,有趣的分析。 – Heinzi 2010-08-06 21:38:07
编译器说什么? – flq 2010-08-06 08:25:48
@Frank:如果我知道,为什么我会问这个问题? – CJ7 2010-08-13 02:15:26