1

I am creating a simple text-game. My Character struct keeps resetting it Can value. What am I doing wrong and how do I fix it? Here is the code:

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;
            }
         }
     }
  }

  //...
}
Linuxios
  • 34,849
  • 13
  • 91
  • 116
  • Did you mean to create a struct? I suspect you have come from a C++ background where the difference between structs and classes is much more subtle. In C# they are very different. Try changing struct to class. – Kevin Holditch Feb 18 '13 at 15:34
  • You've provided 235 lines of code with *very* little indication of what's going wrong. Cut it down to a *short* but complete program demonstrating the problem. Read http://tinyurl.com/so-list (I strongly suspect the problem is the mutable struct, but it's hard to tell with so much irrelevant code.) – Jon Skeet Feb 18 '13 at 15:34
  • @KevinHolditch `goto dovus`? – Sergey Berezovskiy Feb 18 '13 at 15:43
  • 1
    I've tided it up to be of more use to the community, as it is a valid (but poorly written) question. – Dominic Zukiewicz Feb 18 '13 at 15:44
  • To the Edit people: It's pretty confusing when I have written an answer mentioning the type `Karakter`, the method `Dinlen` and the variable `oyuncu`, then after your edits, `Karakter` is respelled, and the method and variable I mention have gone. Will you edit my answer as well, then? – Jeppe Stig Nielsen Feb 18 '13 at 16:00
  • @lazyberezovsky sorry? – Kevin Holditch Feb 18 '13 at 17:13
  • @KevinHolditch sorry, that supposed to be for Kurtuluş Mert – Sergey Berezovskiy Feb 18 '13 at 18:54

6 Answers6

2

A struct is a value type. When you pass it to a method or assign it to another variable, data are copied. You will then operate on a copy.

Consider your method call Dinlen (oyuncu);. It copies the Karakter oyuncu, and then changes the field Can of the copy.

Consider using reference types (class) instead. If you use a struct, consider making it an immutable type. Read the thread Why are mutable structs evil?

Community
  • 1
  • 1
Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

When you are passing struct instance into method, a copy of struct is created (it is passed by value). Any changes to struct inside method does not affect original struct which you passed.

Solutions? Use class instead of struct. Instances of classes passed by reference. Well you can pass structs by reference, but why would you trying to use structs like classes? Use classes instead.

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);
    }
}

BTW I think it will be useful for you to read about Value and Reference Types in .NET

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Hmm, C# language is completely language learning, not trying to do something. :) Thank you.. – Kurtuluş Mert Feb 21 '13 at 07:02
  • In the meantime, what does **override**. – Kurtuluş Mert Feb 21 '13 at 07:16
  • @KurtuluşMert in c# all objects implicitly derived from `object` class, thus all objects have such methods as `ToString() Equals() GetHashCode() GetType()`. ToString is a virtual method, and you can override that method in your objects. Google about inheritance and methods overriding. – Sergey Berezovskiy Feb 21 '13 at 08:36
  • @KurtuluşMert: All classes inherit from `System.Object`, which has a `ToString()` method. It prints out the current class's name. In short, the code sample above wants to 'override' the functionality with a new implementation. – Dominic Zukiewicz Feb 21 '13 at 10:40
0

I believe the problem is you are passing the struct as a variable into your first method, but struct's are value types - i.e. they are copied, not passed by reference.

Changing your struct to class will have the behaviour you require.

P.S. Is there a reason you chose a struct? They are normally used for more advanced scenarios, where the developer knows more about the benefits and flaws of using this type.

Dominic Zukiewicz
  • 8,258
  • 8
  • 43
  • 61
0

You might want to consider using a class instead of a struct.

Paul Gleeson
  • 438
  • 4
  • 10
0

As said, a struct is a value type and passed by copy. You can pass it by ref like this:

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

and call it like this:

var a = new Character();
MainClass.Move(ref a);
Stephane Delcroix
  • 16,134
  • 5
  • 57
  • 85
0

If you want to pass a struct to a method for the purpose of having that method modify it, the method must use a ref qualifier on the parameter. If you pass a struct to a method without a ref parameter, there is no way that the method can modify any fields of that struct.

Note that some people may suggest replacing the struct with a class so that one won't have to use the ref qualifier. That is a dangerous notion, since every method receiving a reference to a mutable class object will be free to cause the object to be mutated at any time thereafter. There's no clean way to pass a reference to a mutable class object without allowing the recipient to mutate it, nor is there any way to be certain that code which is given a class-object reference won't persist it and use it to modify the object at any arbitrary future time. Structures don't have either of these problems.

If an object holds a value-type field e.g. MyBounds of type Drawing.Rectangle, and I call Foo(MyBounds) I can be assured that there is no possibility that Foo will change MyBounds. Further, if I call Bar(ref MyBounds) I can expect that Bar might change MyBounds, but all changes will be complete before the method returns. If Rectangle had been a mutable class type, then without examining Foo and Bar I would have no way of knowing whether the properties of MyBounds might be changed at any arbitrary time in the future.

Someone who doesn't understand that structs are different from classes may be confused by the way structs behave, but all structs with exposed public fields behave the same way, so if one understands how one such struct works, one will understand them all. There is one evil aspect of structures, which is that instance methods and properties defined on a struct will receive this as a ref parameter, but if one attempts to do something like:

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

the system will recognize that myRect cannot be passed as a ref parameter (since it's read-only) and will, without any diagnostic, change the code to:

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

What is evil there, however, is not the fact that Rectangle is mutable, but rather the fact that the compiler assumes the above code substitution is legitimate when calling any and all value-type methods. Unless or until Microsoft gets around to adding an attribute to indicate that calling a particular method on a read-only structure should result in an error rather than performing such substitution, the only safe way to code struct methods that operate on a structure "in-place" would be to use a format like: static void Offset(ref Rectangle it, int x, int y);, in which case Rectangle.Offset(ref myRect, 4, 2); would fail as it should.

supercat
  • 77,689
  • 9
  • 166
  • 211