C# (.NET) 中是否可以使用范围变量?

5

我正在寻找一些类或数据类型,以便我可以定义它的范围。
以下是我正在寻找的伪代码:

[Range(0, 75)] int ChildAge;

应该将此范围规则应用于分配给本年龄的任何int,如下所示。
var MotherAge = ChildAge;
MotherAge = 100; 

母亲年龄应该设置为75岁,这就是我要寻找的内容。

2
C# 不支持这个。 - SLaks
@SLaks 有没有其他的方法来实现这个? - Mohsen Sarkar
1
即使您将“ChildAge”修复为某个范围,也无法限制“MotherAge”的范围。“MotherAge = 100”表示将“MotherAge”设置为“100”,而不考虑“ChildAge”的有效范围。 - p.s.w.g
如果范围只针对孩子年龄,为什么把母亲的年龄设置为75岁?从你的代码看,你似乎是要求限制孩子的范围,但又期望这也会影响到母亲? - Pete Ebdon
你可以创建一个名为 Ageclass,其中包含 minmaxvalue 属性。然后添加一个方法 void SetRange(Age a) 来设置相等的范围。 - Koryu
显示剩余5条评论
3个回答

7
另一种选择是定义自己的数据类型来表示年龄值。这种类型可以强制执行约束条件。
struct Age
{
    const int MinAge = 0;
    const int MaxAge = 75;

    readonly byte value;

    public int Value { get { return value; } }

    private Age(int value) {
        this.value = (byte) Math.Max(MinAge, Math.Min(MaxAge, value));
    }

    public static implicit operator Age(int value) {
        // Throw here if value is out of range, maybe?
        return new Age(value);
    }

    public static implicit operator int(Age age) {
        return age.value;
    }
}

    //usage:
    Age childAge = 12; // 12
    Age motherAge = 100; // 75

编辑:需要指出的是,将“有损”转换暴露为隐式转换通常被认为是不好的实践。我应该将operator int(Age)转换改为explicit。这将需要编写一个显式转换Age age = (Age) 100;,它向API的使用者广告宣传了转换不是“保持身份”的。这类似于从longint或从doublefloat的转换,存在范围/精度损失,因此语言要求您明确表示您理解自己在做什么。


6

C#中没有这样的功能,但是您可以创建一个处理它的类:

public class Age
{
    public Age(int age) : this(0, 75, age) { }
    public Age(int minAge, int maxAge) : this(minAge, maxAge, minAge) { }
    public Age(int minAge, int maxAge, int age)
    {
        this._Minimum = minAge;
        this._Maximum = maxAge;
        this.Value = age;
    }

    private int _Value = 0;
    public int Value
    {
        get
        {
            return _Value;
        }
        set
        {
           CheckRange(value, true);
        }
    }

    private int _Maximum = 0;
    public int MaximumAge
    {
        get
        {
            return _Maximum;
        }
        set
        {
            if (value < _Minimum)
                throw new ArgumentException("MaximumAge");
            _Maximum = value;
            CheckRange(value, false);
        }
    }
    private int _Minimum = 0;
    public int MinimumAge
    {
        get
        {
            return _Minimum;
        }
        set
        {
            if (value > _Maximum)
                throw new ArgumentException("MinimumAge");
            _Minimum = value;
            CheckRange(value, false);
        }
    }

    private void CheckRange(int value, bool setValueAnyway)
    {
        if (value < _Minimum)
            _Value = _Minimum;
        else if (value > _Maximum)
            _Value = _Maximum;
        else if (setValueAnyway)
            _Value = value;
    }
}

现在您的样本已经变老了:
Age childAge = new Age(0,75);
Age motherAge = childAge;
motherAge.Value = 100;   // 75

4

您不需要使用属性,可以使用 property:

private int _age;
public int ChildAge
{
   get { return _age; }
   set
   { 
      if(value > 75)
         _age = 75;
      else if(value < 0)
         _age = 0;
      else
         _age = value;

   } 
}

别忘了声明_age。 - miszczu
这句话的意思是什么?它如何防止MotherAge低于75岁? - Mohsen Sarkar
1
@Madhi:如果你需要重复使用这个功能,你可以将逻辑重构为一个函数,这样它就会变成 _age = LimitValue(value, 0, 75);,并且可以适当地重用 LimitValue - Dan Puzey
@Selman22 这并不会阻止其他整数在0到75之间,但只有ChildAge因为它本身是一个属性。 - Mohsen Sarkar
@Mahdi,你做不到。int 不是引用类型,你不能将 ChildAge 的值绑定到一个整数变量上。 - Selman Genç
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接