-2

I have an Movement class as a property for my objects.

What I want to do is only be able to set determined values for this property, ex:

class Movement
{
    public Direction Moving;
    public Direction Facing;
}

Movement movement = new Movement():

movement.Moving = Direction.Up;
movement.Facing = Direction.Down;

I could make Direction.Up/Down/Left/Right constant strings, but i dont want to be able to set anything that's not Direction.Up/Down/Left/Right' to the property.

but i don't know how to make the Direction class.

Matthew Whited
  • 22,160
  • 4
  • 52
  • 69
Hashino
  • 21
  • 1
  • what you need is an enum; do some research though; the question looks like you haven't put much effort into finding how to do what you want to do – The Bearded Llama Aug 04 '17 at 15:52
  • Do you want it to be that the intellisense will only show you the available options or to really restrict any other values? – Gilad Green Aug 04 '17 at 15:56
  • Why is this downvoted so much, I've seen much worse questions. Im glad that people actually think about which types they might use instead of just using some string. So what if he didn't come up with enums right away, he might be new to the language. – Glubus Aug 04 '17 at 16:11

3 Answers3

2

One way is to use an Enum

public enum Direction 
{
    Up,
    Down,
    Left,
    Right
}

Then if you need to make sure the stored int value is a valid value for your enum: Is there a way to check if int is legal enum in C#?

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
  • 1
    Well strictly speaking, this won't fix the value, there's nothing stopping you writing `movement.Moving = (Direction)42;` – DavidG Aug 04 '17 at 15:53
  • @Davig, while what you are saying is technically true. That doesn't matter for a context such as this. – Matthew Whited Aug 04 '17 at 15:56
  • I think @DavidG means you could have added enforcement code using Enum.IsDefined or whatever it's called. – hoodaticus Aug 04 '17 at 15:57
  • @MatthewWhited How can you possibly know what OP is looking for, particularly when you take into account the penultimate sentence of the question? – DavidG Aug 04 '17 at 15:58
  • That's awesome if you want to slow down you code for no useful reason. – Matthew Whited Aug 04 '17 at 15:58
  • Pretty easily. We are devs and we know what he is trying to do. There is next to no reason to bounds check `Enums` other than slowing down you code from a case that is extremely unlikely to occur since data will be entered using the defined types from the enum and checked with the compiler. If you really want to do something like this bounds checking you should do it with code contracts so it is part of the static analysis and not in the setters. – Matthew Whited Aug 04 '17 at 16:02
  • @MatthewWhited You can assume what "normal" development is, and you may be right, but OP said "but i dont want to be able to set anything that's not...". So whether that's a valid thing to do or not doesn't matter. – DavidG Aug 04 '17 at 16:03
  • You are being pedantic. – Matthew Whited Aug 04 '17 at 16:05
  • @MatthewWhited Yes I should hope so, being a good dev is all about being pedantic. – DavidG Aug 04 '17 at 16:06
  • 1
    No, it's about doing the the best thing and not building extra crap that someone else will have to remove or maintain later. – Matthew Whited Aug 04 '17 at 16:06
  • sorry, i didn't knew about enums and that is common practice to only use it's predetermined values, i ended up using the code i put in my answer, but thanks anyway – Hashino Aug 04 '17 at 17:33
0

You can use an enum and use it like this:

public enum Direction {
    1 = Up,
    2 = Right,
    3 = Down,
    4 = Left
}

public class UseDirection {
    public Direction Dir { public get; private set; }

    public void SetDirection(Direction dir) {
         Dir = dir;
    }
}

However, now if you want to do some manipulations on Directions, or do some calculation, you cannot implement it in Direction since it is an enum.

You could also make an abstract class Direction, and make the actual directions derive from Direction, like this:

public abstract class Direction {


    private class DirectionUp : Direction { }
    private class DirectionDown : Direction { }
    private class DirectionLeft : Direction { }
    private class DirectionRight : Direction { }

    public static Direction Up => new DirectionUp();
    public static Direction Down => new DirectionDown();
    public static Direction Left => new DirectionLeft();
    public static Direction Right => new DirectionRight();
}

Now you can use Direction like this:

public class AggregatesDirection {
     public Direction Dir { public get; private set; }

    public AggregatesDirection() {
         Dir = Direction.Up; //uses the static property in Direction that will use the private constructor of the private class in Direction.
    }
}

This pattern is nice, because you can now just use the Direction interface to do all the stuff relevant to direction, and still have different implementations for when you would, say, relocate something for a given direction in the different direction classes.

You could also just make the classes public and outside of the abstract Direction class, but you would expose the types to the namespace then, which is probably not necessary.

Glubus
  • 2,819
  • 1
  • 12
  • 26
  • 1
    Why would you not just use the setter? – Matthew Whited Aug 04 '17 at 16:06
  • 1
    Eh it's whatever I just typed it without thinking too much, I probably wanted to make it private first and then decided whatever and didn't bother to scroll back up, do you think I should make it neater in order to avoid this confusion? The getter and setters aren't relevant to the pattern Im proposing – Glubus Aug 04 '17 at 16:08
  • error : Direction.DirectionUp is less accessible than Direction.Down i tried this approach before – Hashino Aug 04 '17 at 16:10
  • If that is the case you has the wrong acceessibility on your base class. – Matthew Whited Aug 04 '17 at 16:11
  • "Direction.DirectionUp is less accessible than Direction.Down" How are you even managing to get this error? WIth regards to up and down I mean, also make sure both the static property and the abstract class have the public accessibility modifier. – Glubus Aug 04 '17 at 16:15
  • The signatures of the static properties might've been wrong, Im pretty sure they shouldve returned Direction instead of DirectionUp for instance. I've edited the answer. – Glubus Aug 04 '17 at 16:16
0

i figured it out, here's what did the trick for me:

public class Direction
    {
        private string value;

        private Direction(string value)
        {
            switch (value)
            {
                case "left":
                    {
                        this.value = value;
                        break;
                    }
                case "right":
                    {
                        this.value = value;
                        break;
                    }
                case "up":
                    {
                        this.value = value;
                        break;
                    }
                case "down":
                    {
                        this.value = value;
                        break;
                    }
                default:
                    throw new Exception("Valor invalido");
            }
        }

        public static class Directions
        {
            public static Direction Up = new Direction("up");
            public static Direction Down = new Direction("down");
            public static Direction Left = new Direction("left");
            public static Direction Right = new Direction("right");
        }
    }  

i put the class 'Direction' as public, but it constructor as private, so it can only be instantiated inside itself and its child's, and then made the static class 'Directions' inside it.

so i can easily:

this.directionMoving = Direction.Directions.Down;
this.directionLooking = Direction.Directions.Down;

anywhere in my code, but can't:

Direction move = new Direction();

because it's constructor is only accessible inside itself.

Hashino
  • 21
  • 1
  • How are you going to compare directions now though? All you can do now is compare strings, which is basically the problem you were trying to solve. This is not a solution to your problem tbh. – Glubus Aug 04 '17 at 20:32
  • like this: this.directionMoving = Direction.Directions.Down; the 'Direction.value' is not relevant, im only comparing the objects. and whoever downloads or use my class cant instantiate new elements for the class 'Direction', copy the class and try it – Hashino Aug 05 '17 at 21:39
  • In c# you cannot compare objects like you're assuming you can. Equality comparison is by reference. So if you compare 2 Up directions, equality will fail because they are not the same object. If you would use the type system, you wouldn't have to compare direcitons in the first place. The way you implemented now has loads of potential problems. – Glubus Aug 07 '17 at 08:58