【问题标题】:Retrieve property by reference通过引用检索属性
【发布时间】:2012-03-23 23:14:05
【问题描述】:

我是 C# 新手。我来自Java世界。所以我对以下代码感到困惑:

    class A
    {
        private PointF point;

        public A(PointF point)
        {
            this.point = point;
        }

        public PointF Position
        {
            get { return point; }
        }
    }

我想改变位置属性的X坐标,所以我执行:

        A a = new A(new PointF(1,2));
        PointF p = a.Position;
        p.X = 100;
        Console.WriteLine(a.Position.X); // <--- I have 1 here!

我想知道为什么输出不是 100?据我了解,我收到了有关具有 Position 属性的私有字段的参考。我说的对吗?

我可以在不添加 set-property 和用新的 PointF 对象传播 Position 的情况下更改属性吗?

【问题讨论】:

  • 不,你不能。因为 PointF 是结构体,是值类型。
  • 是的,你可以。你能粘贴你的 PointF 的代码吗,我认为 PointF.X 上的设置器没有做它应该做的事情。 -- 编辑:哦,我没有意识到 PointF 是一个结构而不是一个类......所以你的 p 变量是一个从 a.Position 复制的全新结构。如果您希望它成为引用,则必须将 PointF 封装在一个类中或将新类型定义为一个类。或者你可以使用 Point 类。
  • 你确定吗??!!!我测试了它的工作原理。您是否还可以在示例中添加 PointF 类。编辑:大声笑我也没有看到结构

标签: c# properties pass-by-reference


【解决方案1】:

在 C# 中有两种类型的变量 - 值类型和引用类型。在分配值类型时,它们会被复制 - 对于引用类型,reference 会被复制。

Point 是一个值类型(struct)并且在赋值时被复制。所以:

PointF p = a.Position;

pa.Position副本,与它完全分开。所以:

p.X = 100;

修改pX 的值,保持a.Position.X 不变。

【讨论】:

    【解决方案2】:

    在 C# 中,您有 properties

    class A 
    { 
        public PointF Position {get;set;} 
    
        public A(PointF point) 
        { 
            this.Position = point; 
        } 
    } 
    
    A a = new A(new PointF(1,2));    
        a.Position.X = 100  
        Console.WriteLine(a.Position.X); 
    

    【讨论】:

    • 这甚至不会编译,因为PointFstruct;你不能通过get 改变struct
    【解决方案3】:

    在您的示例中,pa 是两个不同的对象,因此更改前者不会影响后者。

    【讨论】:

      【解决方案4】:

      我想知道为什么您的编译器不给您警告。 这里发生的事情是您没有返回 PointF 引用,它可能是一个值类型,实际上您返回了一个副本。然后您修改该副本 X 属性。这当然行不通。

      【讨论】:

      • 这不是错误(尽管这是不可取的),因为您仍然可以对变异的本地副本做一些有趣的事情。它出错的时间是您直接在属性获取上尝试此操作。
      【解决方案5】:

      PointF 是具有所有后果的值类型。 如果要更改属性中PointF 值的唯一“X”属性,则需要将值复制到变量中,更改“X”属性并设置属性的更改值。

      var cls = new A();
      var point = cls.Point;
      point.X = 15;
      cls.Point = point;
      

      【讨论】:

        【解决方案6】:

        PointF 是一个结构体。在 .Net Framework 中,结构是 valueTypes。所以你的例子总是会打印出 1。

        在课程中使用它并不重要。每次为值类型的变量赋值时,都会被复制。

        【讨论】:

        • 你的意思是它总是打印出 1,而不是 100。
        【解决方案7】:

        没有; PointF 是一个struct,所以它具有复制语义并且不是一个对象;一旦你得到它 - 它是一个单独的和孤立的副本(除非你使用像 ref/out 这样的东西......更微妙)。在您的示例中,该结构实际​​上被复制了多次。

        顺便说一句,这样做的结果是拥有可变结构实际上是一个非常糟糕的主意 - 所以在大多数情况下你应该避免你可以说的场景:

        p.X = 100;
        

        因为这会导致更多的混乱而不是帮助。特别是以下内容完全无效:

        a.Position.X = 100; // won't even compile
        

        (此处编译发现您正在更改仅在突变期间存在的结构副本,这意味着您的更改无处,几乎可以肯定是一个错误)

        【讨论】:

          【解决方案8】:

          你需要使用保存的单词 out(function) 和 ref(when send to function) 通过引用传递参数

          【讨论】:

          • 通过引用传递结构不会让您存储引用;当分配给任何东西时,它将被取消引用。
          猜你喜欢
          • 2013-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-06-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多