C#:函数中的“输出”参数可以是对象属性/变量吗?
例如:
我可以按如下方式调用函数:
someFunction(x, y, out myObject.MyProperty1)
C#:函数中的“输出”参数可以是对象属性/变量吗?
例如:
我可以按如下方式调用函数:
someFunction(x, y, out myObject.MyProperty1)
属性是 [一对 get 和 set] 方法,具有用于调用它们的可爱语法,使它们看起来像字段。
输出参数可以是对字段或基于堆栈的“字段”(即本地)的引用。
语言通常无法弥合这种差距(CLR 和 IL 模型也绝对不会直接解决)。(在@Heinzi 上为 VB 技巧参考 +1)
你不能用 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 调用它,就像这样
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:值不同
Private 9:公开 9:值相同
可以看到传递的PublicInt
成员ByRef
在sampleClass上立即更新,把PrivateInt
暴露的作为属性只在IterateAndUpdate
方法结束后更新。
因此,您会从完全相同的调用约定中获得明显不同的行为,这取决于您如何实现传递的项目(这在调用 时并不明显IterateAndUpdate
。
隐藏错误或进行微小更改的可能性改变预期的行为足以让我希望这个“功能”不存在。
在我看来,这不能正常工作,因此它应该是
a) 已修复,这将花费编译器团队相当大的努力,并可能引入重大更改
或
b) 根本不起作用
不,您不能在 C# 中将属性用作ref
或out
参数,因为 CLR 不支持这一点。传递实例变量应该可以正常工作。
附带说明一下,VB.NET 允许传递属性并使用一种称为“copy back ByRef”的技术,如此 MSDN 博客条目中所述。
传递给 out 参数的参数不能是属性。如果你尝试编译你的代码,你会得到一个编译错误。
属性、索引器或动态成员访问不能作为 out 或 ref 参数传递
原因是属性实际上不是字段(它可能有一个支持字段,但也可能没有)。它是两个方法,称为get_Foo
和set_Foo
。看c#属性和ref参数,为什么不加糖?有关为什么这不起作用的更多解释。
给出编译错误的示例代码:
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();
}
}
您可以将out
参数与字段(或已经说过的本地人)一起使用。