简体   繁体   English

为结构中的字段定义最大值和最小值

[英]Define maximum and minimum for fields in struct

I have a struct and an integer variable on it. 我有一个struct和一个整数变量。 My variable value must be between 1200 and 1599. but in default constructor I have no control in value of variable. 我的变量值必须在1200和1599之间。但是在默认构造函数中,我无法控制变量的值。 How can I do this in my struct ? 如何在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;
    }
}

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. 我将属性与我的setter和Damien_The_Unbeliever的getter结合使用,以使x的初始状态正确。 I also agree with Tim about constants for the "magic numbers" and added that too. 我也同意Tim关于“魔术数字”常量的观点,并补充了这一点。 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. 就像DatVM已经说过的:根据通用C#命名准则,公共字段/属性应以大写字母开头。 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. 最后但并非最不重要的一点:请阅读rexcfnghk的答案,即使它不是真正的答案也是如此,因为他也是绝对正确的。

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. 但是任何变体都会带来一些开销,因此这是否可以接受取决于您。

My variable value must be between 1200 and 1599 我的变量值必须在1200和1599之间

In C#, you cannot define your own default constructor for struct s. 在C#中,您不能为struct定义自己的默认构造struct 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. 如果您有一个MyStruct数组,例如var myArray = new MyStruct[5] ,则将调用MyStruct的默认构造函数,并且myArray中的所有元素的x等于0,这根据您的要求是无效的。

Which is why I believe you have an incorrectly designed struct . 这就是为什么我认为您的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. √DO确保所有实例数据被设置为零,假的,或者为空(如适当时)的状态是有效的。

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. 如果在调用struct的默认构造函数时需要参数验证,请改用一个class

Also, your current design of MyStruct makes it mutable. 另外,您当前对MyStruct设计使其可变。 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. 我将使用带有getter和setter的属性以及一个私有后备字段,在该字段中,您可以实现此逻辑,或者如果该值超出边界,甚至抛出ArgumentOutOfRangeException

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. 最后一点:我建议使用类而不是struct。

You should change x into property instead: 您应该将x改为property

private int _x;

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

PS: as for C# naming convention, it should be called X (capital) instead of x PS:对于C#命名约定,应将其称为X (大写)而不是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; 例如,您可能有一个后备字段int _x_minus_1200; and have a property getter which returns _x_minus_1200 + 1200 . 并具有返回_x_minus_1200 + 1200的属性getter。 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. 我不太热衷于这种方法(通常,我更喜欢结构具有公共字段并表现得像结构,并且结构字段的含义和验证是使用结构的代码的函数),但在某些情况下,它们可以会有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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