【问题标题】:Are properties passed by reference in C#?C# 中的属性是通过引用传递的吗?
【发布时间】:2016-09-30 19:00:13
【问题描述】:

如果我有一些接受布尔值的方法,并且我将一个布尔值属性传递给它,那么该方法会引用该属性吗?还是只是我当时传递的价值?

【问题讨论】:

  • 看答案here
  • 我推荐你阅读 Jon Skeet 的博文Parameter passing in C#
  • @Jonesopolis 是的,我在这个问题上确实看起来不够努力,但值得一问。从愿意提供帮助的人那里得到了答案。

标签: c#


【解决方案1】:

您需要使用ref 关键字在C# 中通过引用传递。在 C# 中,按值传递是默认值。当您传递一个非不可变的类实例时,这有点令人困惑,因为您传递的是一个引用的值。当您将类引用传递给方法时,没有ref 关键字,该方法可以更改实例的属性,但不能更改调用者的引用到那个实例。他们不能改变调用者的引用来引用一个新的实例。但是使用ref(或out),他们可以。

C# 中的 ref 关键字不能与属性一起使用。 See fiddle for the code below:

编译错误(第 8 行,第 15 列):属性、索引器或动态成员访问不能作为 out 或 ref 参数传递

C#

using System;

public class Program
{
    public static void Main()
    {
        var c = new C();
        F(ref c.P);
    }

    public static void F(ref int n) { }

    public class C
    {
        public int P { get; set; }
    }
}

这是因为ref int 是对int 的引用,而具有getter 和setter 的属性不是整数。它是返回整数的代码,或者可以分配一个整数。 C# 确实有一些 魔法,但没有那么神奇。而“魔法”只是编译器生成的代码。他们可以做到这一点。但他们没有。

我会为了提高运行时效率,他们希望将其保留为指针(或与其非常相似的任何东西)上的简单语法糖。但这种猜测可能是非常错误的。

【讨论】:

  • 实际上在概念上是可能的。属性在其他上下文中被视为变量(您可以使用赋值运算符对其进行赋值)。 VB实际上支持你描述的假设功能,如果没有记错的话,C#只是懒得添加它。
  • @Servy 哦,当然这在概念上是可能的——你可以生成代码来做几乎任何事情(除非这是你不能生成代码来做的事情)。
  • 好吧,在你的情况下,它是一个自动属性,这是可能的。但是当我将其更改为public int P {get{ return DateTime.Now.Millisecond;} set{ //Do nothing } } 时会发生什么,您将通过实现该属性来完全破坏某人的代码。这就是为什么它不是一个选项。
  • @aquinas 取决于他们如何实现它。以我有限的智慧,我的第一个想法是让ref n 简单地获取属性的getter 和setter 并使用它们——如果n 是一个字段或一个变量,则生成一个简单的getter/setter。在这种情况下,一个无操作的二传手不会打破它没有打破的任何期望。因此,您会在这里遇到一些“行为不符合预期”的问题,在拔牙将代码从中取出后,您会发现 setter 是空的。根本没有二传手? “不能将属性或索引器 P 分配给 - 它是只读的”。
  • @EdPlunkett 我认为这样做的困难在于,这意味着必须为相同的方法生成不同的代码,具体取决于传递给它的参数。这与当前编译方法的方式有很大不同(其中为方法生成的代码仅取决于方法的内容)。为了做到这一点,我认为编译器必须悄悄地生成一个单独的方法重载,该方法将 getter 和 setter 作为委托或其他东西。
【解决方案2】:

你当时传递的价值

【讨论】:

  • 好吧,就是我想的那样。因为该属性的评估方式类似于方法的评估方式,对吧?
  • 如果需要,您可以通过将属性包装在委托中来传递对属性的引用,委托在被调用函数中进行评估,但需要有充分的理由这样做。
【解决方案3】:

它将传递值。

默认情况下,C# 中的所有参数都复制该值。例外情况是当属性使用outref 进行注释时,在这种情况下,参数实际上是对值的引用,而不是值本身。

虽然通常可以通过引用将参数传递给方法,但不能通过引用传递属性的值,C# 根本不支持它。如果您的方法注释为ref,那么您的代码将无法编译。

【讨论】:

    猜你喜欢
    • 2011-01-23
    • 2010-11-27
    • 2010-12-24
    • 1970-01-01
    • 2020-04-01
    • 2018-07-09
    • 1970-01-01
    相关资源
    最近更新 更多