简体   繁体   中英

C# - Reset the value of struct on class or struct

I'm trying to code some script with Unity, and I have some issue to understand how struct works.

Start with a base of code:

 public class Engine : MonoBehaviour {

   public Hero selectedHero;
   public List<Hero> heroes;

   public struct Hero {
     public string name;
     public Hero(string n) {
       name = n;
     }
   }
 } 

First I try to make some function to select/unselect..

/* ... */
public Hero getSelected(Hero h) {
  return selectedHero;
}
public void setSelected(Hero h) {
  selectedHero = h;
}
public bool hasSelected(Hero h) {
  return (selectedHero != null);
}
public void clearSelected() {
  selectedHero = null; //  This is not working ! :'(
}
/* ... */

And I got this error:

Cannot convert null to Hero because it is a value type

I read a lot's about C# and Unity Scripting and the answer is:

A struct can't be null in the same way that an int can't be null, and a float can't be null - they're all value types

But ? What's the real solution !? I used two ugly solution to avoid this:

Solution #1 I can put a public bool hasSelected and always test this one before use the selected attribute.

Solution #2 Is to create a List<Hero> selected instead of simple Hero and handle if the Length is 0 or 1.

Does exist a better solution, more clean ?!

Bonus question: How to create a function who return a single Hero based on a test, my best (ugly) solution:

public Hero GetHero(string name) {
    foreach (Hero hero in heroes) {
        if (hero.name == name) {
            return hero;
        }
    }
    return null; // Not working ?! What can I return ?!
 }

If you need your type to be nullable, it sounds like you should make Hero a class (reference type) instead of a struct (value type). The changes to your code will be minimal, just swap the keyword:

public class Hero {
    public string name;
    public Hero(string n) {
        name = n;
    }
}

If there is a reason you should be using Struct instead of class , then use default of to check your structs.

Some times your program may behave (or mis-behave) differently when it expects a struct and you pass a class.

So here are the changes for two of your methods:

       public bool hasSelected(Hero h)
        {
            return !(h.Equals(default(Hero)));
        }
        public void clearSelected()
        {
            selectedHero = default(Hero); 
        }

About main question :

Value types (int, struct, etc..) cannot express null in its binary representation, that's why .NET does not allow. But the .NET it has the Nullable<T> struct that add extra bytes for null representation.

About select/unselect functions

I have refactored your code to work with struct:

public Hero GetSelected()
{
    return selectedHero;
}

public void SetSelected(Hero h)
{
    selectedHero = h;
}

public bool HasSelected()
{
    return !(selectedHero.Equals(default(Hero)));
}

public void ClearSelected()
{
    selectedHero = default(Hero);
}

About bonus question :

That's simple, use LinQ =)

public Hero GetHero(string name)
{
    return heroes.Where(w => w.name.Equals(name)).FirstOrDefault();
}

PS: The 'default value' It is other than 'Null Value'.

References:

I hope that helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM