Question

I have a struct and an integer variable on it. My variable value must be between 1200 and 1599. but in default constructor I have no control in value of variable. How can I do this in my struct?

struct MyStruct
{
    public int x;

    public MyStruct(int x)
    {
         if(x>1599)
              this.x=1599;
         else if(x<1200)
              this.x=1200;
         else
              this.x=x;
    }
}
Was it helpful?

Solution

Another variant on using a property and a private backing field:

struct MyStruct
{
    private int x;

    public MyStruct(int x)
    {
        if (x > 1599)
            this.x = 399;
        else if (x < 1200)
            this.x = 0;
        else
            this.x = x - 1200;
    }

    public int X { get { return x+1200; } }
}

Which ensures that the default constructed value is "in range".

But any variant is going to introduce some overhead, so it's up to you whether this is acceptable.

OTHER TIPS

Use a property with a backing field:

struct MyStruct
{
    private const int MIN_VALUE = 1200;
    private const int MAX_VALUE = 1599;

    private int x;
    public int X 
    {
        get { return x + MIN_VALUE; }
        set
        {
            if(value > MAX_VALUE)
                x = MAX_VALUE;
            else if(value < MIN_VALUE)
                x = MIN_VALUE;
            else
                x = value;
            x -= MIN_VALUE;
        }
    }

    // constructor is not really needed anymore, but can still be added
}

I combined the property with my setter and Damien_The_Unbeliever's getter to get the initial state of x right. I also agree with Tim about constants for the "magic numbers" and added that too. So please give this two also credit for "my answer".

Also as DatVM already said: Public fields/properties should start with a capital letter according to the common C# naming guidlines. This also enalbes you to use the same name for the backing field, but starting with a small letter (I personally do NOT like the ugly _)...

And last but not least: Please read rexcfnghk's answer, even if it is not really an answer, as he is also absolutely correct.

My variable value must be between 1200 and 1599

In C#, you cannot define your own default constructor for structs. If you have an array of MyStruct, like var myArray = new MyStruct[5], the default constructor of MyStruct will be invoked and elements in myArray will have all have x equals to 0, which is invalid according to your requirement.

Which is why I believe you have an incorrectly designed struct. According to the Framework Design Guidelines

DO ensure that a state where all instance data is set to zero, false, or null (as appropriate) is valid.

This prevents accidental creation of invalid instances when an array of the structs is created.

If you need argument validation when your struct's default constructor is invoked, use a class instead.

Also, your current design of MyStruct makes it mutable. please take a look on why Mutable structs are evil.

I would use properties with getter and setter and a private backing field where you can implement this logic or even throw an ArgumentOutOfRangeException if the value is outside of the boundaries.

Here is an example:

struct MyStruct
{
    private const int MIN_VALUE = 1200;
    private const int  MAX_VALUE = 1599;

    private int _X;

    public int X
    {
        get { return _X; }
        set { _X = checkBoundaries(value); }
    }

    private static int checkBoundaries(int x)
    {
        if (x > MAX_VALUE)
            return MAX_VALUE;
        else if (x < MIN_VALUE)
            return MIN_VALUE;
        else
            return x;
    }

    public MyStruct(int x)
    {
        _X = checkBoundaries(x);
    }
}

It's good practices to always use properties even if you don't need to restrict the access in the first place. Then it's easier to implement such a logic if you need.

One final note: i would suggest to use a class instead of struct.

You should change x into property instead:

private int _x;

public int x {
    get
    {
        return _x;
    }
    set
    {
        _x = value;
        if (_x > 1599)
        {
            _x = 1599
        }
        else if (_x < 1200)
        {
            _x = 1200
        }
    }
}

P.S: as for C# naming convention, it should be called X (capital) instead of x

A struct can be made to have a default value if, rather than using a public field, one uses a private field and a public property which transforms the field's value in such a way that its default value will map to the desired default for the structure. For example, you could have a backing field int _x_minus_1200; and have a property getter which returns _x_minus_1200 + 1200. I'm not hugely keen on such approaches (generally I prefer for structures to have public fields and behave like structures, and have the meaning and validation of structure fields be a function of the code that uses the structures) but in some cases they can be helpful.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top