不能修改返回值,因为它不是一个变量。

6

我有一个名为 BaseRobot 的类:

  var robot2 = new BaseRobot(0, 0, 0);
  private Point mHome;
  public Point Home
  {
      get { return mHome; }
  }

这是创建原始主页的位置,我想在program.cs中创建一个新主页。我有以下代码,但它不起作用,出现错误信息:

无法修改返回值,因为它不是一个变量。

代码:

     robot2.Home.X = 1
     robot2.Home.Y = 5;

            {

                Console.WriteLine("===New robot at specified home position===");
                StringBuilder ab = new StringBuilder();
                ab.AppendFormat("Robot#2 has home at <{0},{0}>.\r\n ", robot2.Home.X, robot2.Home.Y);
                ab.AppendFormat("It is facing {0} ", robot2.Orientation);
                ab.AppendFormat("and is currently at <{0},{0}>.\r\n", robot2.Position.X, robot2.Position.Y);
                Console.WriteLine(ab.ToString());
            }

如何为x和Y分配新值?


5
@MitchWheat 和其他同学们。这不是一个重复的问题,你们应该尝试实际阅读两个问题。 - musefan
你的 Point 的声明和命名空间是什么? - H H
7个回答

20
你需要直接设置Home属性,通常最好创建一个新的Point对象...
robot2.Home = new System.Drawing.Point(1, 5);//x, y

此外,为了允许这一点,您需要对 Home 属性应用 set 访问器...

public Point Home
{
    get { return mHome; }
    set { mHome = value; }
}
如果您想了解为什么编译器不允许您直接将值分配给X属性,请查看这里的一些答案

我已经完成了这个任务,但现在在主程序中收到一条消息,说“Point”找不到。 - user2657462
@user2657462:那么你可能没有正确包含命名空间。在创建新的“Point”时,可以明确添加它(请参见我的编辑)。或者在类文件顶部包含它:“include System.Drawing;”(或在VS中使用“解析”)。 - musefan
1
当你第十次看到它时,这显然是如此明显。无论如何+1。再获得一个优秀答案徽章。 - ouflak

7

你需要按照以下方式更改你的代码:

private Point mHome;

public Point Home
{
   get { return mHome; }
   set { mHome = value; }
}

并将其设置为以下内容:

robot2.Home = new Point(1, 5);

结构体是不可变的,因此更改值实际上会返回新的Point实例,但您的属性没有setter。


1
+1 提到结构体是不可变的。这在得票最高的帖子中没有提到,这很重要,可以知道为什么开头帖子中的代码无法工作。 - Tseng
3
结构体不是不可变的,它们具有值语义。除非特意设计为不可变,否则可以修改结构体类型的局部变量或字段。 - Anton Tykhyy

5

我曾经在某处看到这样一个好的解释(我将适应当前情况):

这是C#设计的一个糟糕部分。

在内部,像robot2.Home这样的东西被实现为属性,因此当你尝试给Home.X赋值时,在幕后会调用Home的get函数(这就是"Cannot modify the return value of .."的来源)。当这样做时,你无法将值分配给Point结构体中的单个成员(X),而必须分配整个结构体。

因此,在C#中,你需要将值读取到一个Point中,然后修改它:

robot2.Home = robot2.Home + new Point (deltaX, deltaY);

或者(如果我们不关心以前的值(在这种情况下)),只需将其分配给新值:
robot2.Home = new Point (1f, 5f);

提示:当然,您还需要为Home属性添加setter(正如其他答案中提到的那样)。


2
您需要为 Home 属性添加一个 set 访问器:
   private Point mHome;
   public Point Home
   {
       get { return mHome; }
       set { mHome = value; }
   }

2

System.Drawing.Point是一个值类型,这意味着你的Home属性返回的是私有mHome副本,而不是对它的引用。

你需要为Home属性添加setter,并调整你的代码:

  private Point mHome;
  public Point Home
  {
      get { return mHome; }
      set {mHome = value;}
  }

调整您的呼叫代码以将新点分配给主页:
   robot2.Home = new Point(1, 5);

1
除了已经提到的公共属性设置器解决方案外,您还可以:
创建设置器方法 public void SetHomeX(double x) { mHome.X = x; } public void SetHomeY(double y) { mHome.Y = y; } 将字段公开为公共属性 public Point Home; 注意:将字段公开为公共属性通常被认为不是一个好的解决方案。但在某些情况下可能会很方便。

0

这只是一个猜测,但 X 和 Y 属性可能只是像你的 Home 属性一样的 getter。

你的机器人类中是否有移动位置的函数?如果有,请使用它。如果没有,请提供完整的示例。


不要忘记,如果您在发布后意识到已经有另一个更好或相同的答案被发布,删除您的帖子以避免在问题中添加没有任何贡献的答案是没有成本的。 - Michelle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接