为什么我的C#结构在传递到方法时会被重置

为什么我的C#结构在传递到方法时会被重置,c#,struct,parameter-passing,reset,C#,Struct,Parameter Passing,Reset,我正在创建一个简单的文本游戏。我的字符结构一直在重置它的Can值。我做错了什么?我如何修复它?代码如下: namespace MyNamespace { struct Character { public float Can; //... } class MainClass { public static void Move (Character a) { bool cal = true;

我正在创建一个简单的文本游戏。我的
字符
结构一直在重置它的
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;
            }
         }
     }
  }

  //...
}
名称空间MyNamespace
{
结构字符
{
公共浮动罐;
//...
}
类主类
{
公共静态无效移动(字符a)
{
布尔-卡尔=真;
while(cal)
{
睡眠(500);

如果(a.Can将结构实例传递给方法时,会创建一个结构副本(按值传递)。对方法内部结构的任何更改都不会影响传递的原始结构

解决方案?使用类而不是结构。类的实例通过引用传递。您可以通过引用传递结构,但为什么要尝试像类一样使用结构?请使用类

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中的相关内容会对您有所帮助。我认为问题在于您正在将
结构作为变量传递到第一个方法中,但结构是值类型,即它们是复制的,而不是通过引用传递的

struct
更改为
class
将具有所需的行为


<> P.S.S.有一个原因,你选择了一个<代码>结构> /代码>吗?它们通常用于更高级的场景,开发人员对使用这种类型的好处和缺点有更多的了解。

你可能想考虑使用一个类而不是一个结构。< > >代码>结构> <代码>是一个<强>值类型< /强>。当你把它传递给一个方法时或者将其分配给另一个变量,数据将被复制。。然后,您将对副本进行操作

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


考虑使用引用类型(<代码>类< /代码>)。如果使用<代码>结构> <代码>,请考虑将其设为不可变类型。如所述,读取线程

,结构是一个值类型,由副本传递。
public static void Move (ref Character a)
{
...
}
var a = new Character();
MainClass.Move(ref a);
这样称呼它:

public static void Move (ref Character a)
{
...
}
var a = new Character();
MainClass.Move(ref a);

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

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

如果一个对象持有一个值类型字段,例如
MyBounds
,类型为
Drawing.Rectangle
,我调用
Foo(MyBounds)
,我可以确定
Foo
不可能改变
MyBounds
。此外,如果我调用
Bar(ref MyBounds)
我可以预期
Bar
可能会更改
MyBounds
,但所有更改都将在方法返回之前完成。如果
Rectangle
是一个可变的类类型,那么在不检查
Foo
Bar
的情况下,我将无法知道
MyBounds
的属性是否可以更改在将来的任何时候都可以任意选择

不了解结构与类不同的人可能会对结构的行为方式感到困惑,但所有具有公开公共字段的结构的行为方式都是相同的,因此,如果理解一个这样的结构是如何工作的,就会理解它们。结构有一个邪恶的方面,即实例方法和属性结构上的fined将作为
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开始添加一个属性,指示在只读结构上调用特定方法ure应该导致错误,而不是执行这种替换,对“就地”在结构上操作的结构方法进行编码的唯一安全方法是使用如下格式:
静态无效偏移量(ref Rectangle it,int x,int y);
,在这种情况下,
矩形偏移量(ref myRect,4,2)

将是失败的。

是否意味着创建一个结构?我怀疑你来自C++背景,结构和类之间的差别更微妙。在C语言中,它们非常不同。尝试将结构转换为类。你已经提供了235行代码,很少有什么出错的迹象。一个简短但完整的程序演示了这个问题。请阅读(我强烈怀疑问题是可变结构,但用这么多不相关的代码很难判断。)@KevinHolditch
goto-dovus
?我已经整理好了它,以便对社区更有用,因为它是一个有效的(但写得很差)问题。对于编辑人员:当我写了一个提到类型
Karakter
、方法
Dinlen
和变量
oyuncu
的答案,然后在您编辑后,,这是相当令人困惑的