1

我正在创建一个简单的文本游戏。我的Character结构不断重置它的Can值。我做错了什么,我该如何解决?这是代码:

namespace MyNamespace
{
   struct Character
   {
      public float Can;
      //...
   }

   class MainClass
   {
      public static void Move (Character a)
      {
         bool cal = true;

         while (cal) 
         {
            Thread.Sleep(500);

            if(a.Can <= 100)
            {
               a.Can += 1;
            }
            else
            {
               cal = false;
            }
         }
     }
  }

  //...
}
4

6 回答 6

2

Astruct是一个值类型。当您将其传递给方法或将其分配给另一个变量时,数据将被复制。然后,您将对副本进行操作。

考虑您的方法调用Dinlen (oyuncu);。它复制 Karakter oyuncu,然后更改Can 副本的字段。

考虑改用引用类型 ( class)。如果您使用 a struct,请考虑将其设为不可变类型。阅读线程为什么可变结构是邪恶的?

于 2013-02-18T15:48:57.797 回答
0

当您将 struct 实例传递给方法时,会创建 struct 的副本(它是按值传递的)。对结构内部方法的任何更改都不会影响您传递的原始结构。

解决方案?使用类而不是结构。通过引用传递的类的实例。好吧,您可以通过引用传递结构,但是为什么要尝试使用类之类的结构呢?改用类。

class Karakter
{
    public string Isim { get; set; }
    public float Can { get; set; }
    public int Seviye { get; set; }
    public int Exp { get; set; }
    public float Guc { get; set; }
    public string Irk { get; set; }
    public int vExp { get; set; }

    public override string ToString()
    {
        return String.Format("Adınız:{0}\nIrkınız:{1}\nCan:{2}\nGuc:{3}", 
                             Isim, Irk, Can, Guc);
    }
}

顺便说一句,我认为阅读.NET 中的值和引用类型对您很有用

于 2013-02-18T15:35:11.600 回答
0

我相信问题是您将struct作为变量传递给您的第一个方法,但结构是值类型 - 即它们是复制的,而不是通过引用传递的。

改变你structclass有你需要的行为。

PS你选择a有什么原因struct吗?它们通常用于更高级的场景,开发人员更了解使用这种类型的好处和缺陷。

于 2013-02-18T15:36:32.523 回答
0

您可能需要考虑使用类而不是结构。

于 2013-02-18T15:48:35.443 回答
0

如前所述,结构是一种值类型,并通过副本传递。您可以像这样通过 ref 传递它:

public static void Move (ref Character a)
{
...
}

并这样称呼它:

var a = new Character();
MainClass.Move(ref a);
于 2013-02-18T15:52:59.960 回答
0

如果要将结构传递给方法以使该方法对其进行修改,则该方法必须ref在参数上使用限定符。如果将结构传递给不带ref参数的方法,则该方法无法修改该结构的任何字段。

请注意,有些人可能会建议将结构替换为类,这样就不必使用ref限定符。这是一个危险的概念,因为每个接收到对可变类对象的引用的方法都可以自由地导致该对象在此后的任何时间发生变异。没有干净的方法来传递对可变类对象的引用而不允许接收者对其进行变异,也没有任何方法可以确定给定类对象引用的代码不会持久保存它并使用它来修改在任意未来时间的对象。结构没有这些问题。

如果一个对象包含一个值类型字段,例如MyBoundstype Drawing.Rectangle,并且我打电话给我,Foo(MyBounds)我可以确信它不可能发生Foo变化MyBounds。此外,如果我打电话,Bar(ref MyBounds)我可以预期这Bar可能会改变MyBounds,但所有的改变都将在方法返回之前完成。如果Rectangle它是一个可变类类型,那么如果不进行检查FooBar我将无法知道MyBounds未来的任何时候是否会更改 的属性。

不了解结构体与类不同的人可能会对结构体的行为方式感到困惑,但所有具有公开公共字段的结构体的行为方式都是相同的,因此,如果了解一个这样的结构体是如何工作的,就会理解所有结构体。结构有一个邪恶的方面,即在结构上定义的实例方法和属性将this作为ref参数接收,但如果尝试执行以下操作:

readonly System.Drawing.Rectangle myRect = whatever;
...
myRect.Offset(4,2);

系统将识别出myRect不能作为ref参数传递(因为它是只读的)并且将在没有任何诊断的情况下将代码更改为:

readonly System.Drawing.Rectangle myRect = whatever;
...
System.Drawing.Rectangle temp = myRect;
temp.Offset(4,2);

然而,那里的邪恶不是Rectangle可变的事实,而是编译器假定上述代码替换在调用任何和所有值类型方法时是合法的这一事实。除非或直到 Microsoft 开始添加一个属性以指示在只读结构上调用特定方法会导致错误而不是执行此类替换,否则对结构上操作的结构方法进行编码的唯一安全方法“in- place" 将使用类似: 的格式static void Offset(ref Rectangle it, int x, int y);,在这种情况下Rectangle.Offset(ref myRect, 4, 2);会失败。

于 2013-02-18T17:10:56.467 回答