C#:可以“输出”函数中的参数是对象属性/变量吗?

发布于 2024-09-12 18:44:43 字数 138 浏览 13 评论 0原文

C#:函数中的“输出”参数可以是对象属性/变量吗?

例如:

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

someFunction(x, y, out myObject.MyProperty1)

C#: can 'out' parameters in functions be object properties/variables?

eg:

can I call a function as follows:

someFunction(x, y, out myObject.MyProperty1)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

以为你会在 2024-09-19 18:44:43

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

输出参数可以是对字段或基于堆栈的“字段”(即局部变量)的引用。

语言通常无法弥补这一差距(并且 CLR 和 IL 模型也绝对不能直接解决)。 (+1 @Heinzi 的 VB 欺骗参考)

Properties are [a pair of get and set] methods with a cute syntax for invoking them that makes them look like fields.

Out parameters can be references to fields or stack based 'fields' (i.e., locals).

The bridging of this gap is generally not addressed by languages (and definitely not directly by the CLR and IL model). (+1 on @Heinzi for the VB trickery references)

猥琐帝 2024-09-19 18:44:43

您无法使用 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:值相同

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

因此,您从完全相同的调用约定中获得明显不同的行为,这取决于您如何实现传递的项目(从对 IterateAndUpdate 的调用来看,这一点并不明显。
隐藏错误或进行微小更改改变预期行为的潜力足以让我希望这个“功能”不存在。

在我看来,这不能正常工作,因此它应该是
a) 已修复,这需要编译器团队付出相当大的努力,并且可能会引入重大更改

b) 根本不起作用

You can't do this with C#.
You can with VB.Net, but I consider this a bad idea. The following code and output show how it does it and shows why I think it's a bad idea, to the point where I wish VB.net also didn't allow this

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

Now call this from a sub main, like so

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

This outputs

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

You can see that the PublicInt member when passed ByRef is updated immediately on sampleClass, put the PrivateInt exposed as a property is only updated after the IterateAndUpdate method ends.

Therefore, you get markedly different behaviour from exactly the same calling convention, and it depends on how you've implemented the item passed (which isn't at all obvious looking at the call to IterateAndUpdate.
The potential to hide bugs, or have small changes change expected behaviour is enough for me to wish this "feature" didn't exist.

To my mind this does not work correctly, therefore it should either be
a) Fixed, which would take considerable effort for the compiler team, and possibly introduce breaking changes
or
b) Not work at all

梦毁影碎の 2024-09-19 18:44:43

不可以,您不能在 C# 中使用属性作为 refout 参数,因为 CLR 不支持这一点。传递实例变量应该可以正常工作。

附带说明一下,VB.NET 允许传递属性并使用称为“copy back ByRef”的技术,如 此 MSDN 博客条目

No, you cannot use a property as a ref or out parameter in C#, since the CLR does not support this. Passing an instance variable should work fine.

As a side note, VB.NET allows passing properties and uses a technique called "copy back ByRef", as explained in this MSDN blog entry.

热风软妹 2024-09-19 18:44:43

传递给输出参数的参数不能是属性。如果您尝试编译代码,您将收到编译错误。

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

原因是属性实际上不是字段(它可能有支持字段,但也可能没有)。它有两个方法,分别称为 get_Fooset_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();
    }
}

The argument passed to an out parameter cannot be a property. If you try to compile your code you will get a compile error.

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

The reason is that a property is not actually field (it might have a backing field, but it might not). It is two methods called get_Foo and set_Foo. See c# property and ref parameter, why no sugar? for more explanation of why this doesn't work.

Example code that gives the compile error:

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();
    }
}
香草可樂 2024-09-19 18:44:43

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

You can use the out parameter with fields (or locals as said already).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文