为结构中的字段定义最大值和最小值
本文关键字:最大值 最小值 定义 字段 结构 | 更新日期: 2023-09-27 18:00:54
我有一个struct
和一个整数变量。我的变量值必须在1200到1599之间。但在默认构造函数中,我无法控制变量的值。如何在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;
}
}
关于使用属性和私有后台字段的另一个变体:
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; } }
}
这样可以确保默认构造的值"在范围内"。
但任何变体都会引入一些开销,所以这是否可以接受取决于您。
使用带有支持字段的属性:
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
}
我将属性与我的setter和Damien_the_Unbeliever的getter相结合,以获得正确的x
的初始状态。我也同意蒂姆关于"幻数"常数的观点,并补充了这一点。因此,请将这两个也归功于"我的答案"。
正如DatVM已经说过的:根据常见的C#命名指南,公共字段/属性应该以大写字母开头。这也允许你使用相同的名字作为背景字段,但以一个小字母开头(我个人不喜欢丑陋的_(。。。
最后但同样重要的是:请阅读rexcfnghk的答案,即使这不是一个真正的答案,因为他也是绝对正确的。
我的变量值必须在1200和1599 之间
在C#中,您不能为struct
s定义自己的默认构造函数。如果您有一个MyStruct
的数组,如var myArray = new MyStruct[5]
,则会调用MyStruct
的默认构造函数,并且myArray
中的元素都具有等于0的x
,根据您的要求,这是无效的。
这就是为什么我认为你有一个设计错误的struct
。根据框架设计指南
√DO确保所有实例数据设置为零、假或空(视情况而定(的状态有效。
这样可以防止在创建结构数组时意外创建无效实例。
如果在调用struct
的默认构造函数时需要参数验证,请改用class
。
此外,您当前的MyStruct
设计使其可变。请看一下为什么可变结构是邪恶的。
我会使用getter和setter的属性以及一个私有的支持字段,在那里您可以实现这个逻辑,甚至在值超出边界时抛出ArgumentOutOfRangeException
。
这里有一个例子:
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);
}
}
即使一开始不需要限制访问,也要始终使用属性,这是一种良好的做法。如果需要的话,实现这样的逻辑会更容易。
最后一点:我建议使用类而不是结构。
- 不能在结构中定义默认构造函数,因此不能阻止使用默认值0初始化
_X
- 不能用内联的最小值初始化
_X
,因为结构中也不允许这样做 - 如果你的类型越来越复杂,并且你有这样的规则,这是一个很好的指标,表明类会更合适
您应该将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
}
}
}
p.S:对于C#命名约定,应该称为X
(大写(,而不是x
如果不是使用公共字段,而是使用私有字段和公共属性来转换字段的值,从而使其默认值映射到结构所需的默认值,则可以使结构具有默认值。例如,您可以有一个后备字段int _x_minus_1200;
,并有一个返回_x_minus_1200 + 1200
的属性getter。我对这种方法不太感兴趣(通常我更喜欢结构具有公共字段,表现得像结构,并将结构字段的含义和验证作为使用结构的代码的函数(,但在某些情况下,它们可能会有所帮助。