C# 表示百分比、概率或库存水平的

C# 表示百分比、概率或库存水平的,c#,.net,data-structures,C#,.net,Data Structures,在.NET3.5中是否有一种简洁的方法来表示有界数值 我的意思是一个值,比如百分比0-100概率0-1或股票水平0或更高 如果试图进行超出范围的赋值,我希望抛出ArgumentOutOfRangeException或等效值。我还希望静态MaxValue和MinValue属性可用 有人在a中提出,这是结构的一种很好的使用。事实上,这是MS Press 70-526考试学习指南中用作“使用结构的位置”示例的类型。一小组

在.NET3.5中是否有一种简洁的方法来表示有界数值

我的意思是一个值,比如百分比0-100概率0-1或股票水平0或更高

如果试图进行超出范围的赋值,我希望抛出ArgumentOutOfRangeException或等效值。我还希望静态MaxValue和MinValue属性可用


有人在a中提出,这是结构的一种很好的使用。

事实上,这是MS Press 70-526考试学习指南中用作“使用结构的位置”示例的类型。一小组<16字节的数据,具有值语义,最好设计为结构,而不是类。

事实上,这是MS Press 70-526考试学习指南中用作“使用结构的位置”示例的类型。一小组<16字节的数据,具有值语义,最好设计为一个结构,而不是一个类。

我认为没有像Ada这样的内置方式,但您可以轻松创建一个像RestrictedRange这样的类型,该类型具有最小值和最大值以及当前值:

public class RestrictedRange<T> where T : IComparable
{        
    private T _Value;

    public T MinValue { get; private set; }
    public T MaxValue { get; private set; }

    public RestrictedRange(T minValue, T maxValue)
        : this(minValue, maxValue, minValue)
    {
    }

    public RestrictedRange(T minValue, T maxValue, T value)
    {
        if (minValue.CompareTo(maxValue) > 0)
        {
            throw new ArgumentOutOfRangeException("minValue");
        }

        this.MinValue = minValue;
        this.MaxValue = maxValue;
        this.Value = value;
    }

    public T Value
    {
        get
        {
            return _Value;
        }

        set
        {
            if ((0 < MinValue.CompareTo(value)) || (MaxValue.CompareTo(value) < 0))
            {
                throw new ArgumentOutOfRangeException("value");
            }
            _Value = value;
        }
    }

    public static implicit operator T(RestrictedRange<T> value)
    {
        return value.Value;
    }        

    public override string ToString()
    {
        return MinValue + " <= " + Value + " <= " + MaxValue;
    }
}
由于存在自动获取值的隐式转换,这将起作用:

var adultAge = new RestrictedRange<int>(18, 130, 21);
adultAge.Value++;
int currentAge = adultAge; // = 22
另外,你也可以这样做

var stockLevel = new RestrictedRange<int>(0, 1000)
var percentage = new RestrictedRange<double>(0.0, 1.0);

我认为没有像Ada这样的内置方式,但您可以轻松创建一个像RestrictedRange这样的类型,该类型具有最小值和最大值以及当前值:

public class RestrictedRange<T> where T : IComparable
{        
    private T _Value;

    public T MinValue { get; private set; }
    public T MaxValue { get; private set; }

    public RestrictedRange(T minValue, T maxValue)
        : this(minValue, maxValue, minValue)
    {
    }

    public RestrictedRange(T minValue, T maxValue, T value)
    {
        if (minValue.CompareTo(maxValue) > 0)
        {
            throw new ArgumentOutOfRangeException("minValue");
        }

        this.MinValue = minValue;
        this.MaxValue = maxValue;
        this.Value = value;
    }

    public T Value
    {
        get
        {
            return _Value;
        }

        set
        {
            if ((0 < MinValue.CompareTo(value)) || (MaxValue.CompareTo(value) < 0))
            {
                throw new ArgumentOutOfRangeException("value");
            }
            _Value = value;
        }
    }

    public static implicit operator T(RestrictedRange<T> value)
    {
        return value.Value;
    }        

    public override string ToString()
    {
        return MinValue + " <= " + Value + " <= " + MaxValue;
    }
}
由于存在自动获取值的隐式转换,这将起作用:

var adultAge = new RestrictedRange<int>(18, 130, 21);
adultAge.Value++;
int currentAge = adultAge; // = 22
另外,你也可以这样做

var stockLevel = new RestrictedRange<int>(0, 1000)
var percentage = new RestrictedRange<double>(0.0, 1.0);

我可能会创建一个类来表示有界值

public class Percentage
{
    public static readonly double MinValue = 0.0;
    public static readonly double MaxValue = 100.0;

    private double value;
    public double Value
    {
       get { return this.value; }
       set
       {
            if (value < MinValue || value > MaxValue)
            {
                throw new ArgumentOutOfRangeException("...");
            }
            this.value = value;
       }
}

但是,如果您的数据存储在数据库中,通常可以避免这种情况,只需对值使用自然基础类型,并在数据库和数据验证方法中实施约束。如果需要,可以将最小值/最大值存储在配置中。

我可能会创建一个类来表示有界值

public class Percentage
{
    public static readonly double MinValue = 0.0;
    public static readonly double MaxValue = 100.0;

    private double value;
    public double Value
    {
       get { return this.value; }
       set
       {
            if (value < MinValue || value > MaxValue)
            {
                throw new ArgumentOutOfRangeException("...");
            }
            this.value = value;
       }
}

但是,如果您的数据存储在数据库中,通常可以避免这种情况,只需对值使用自然基础类型,并在数据库和数据验证方法中实施约束。如果需要,可以将最小值/最大值存储在配置中。

当然,您可以通过在setter中检查来强制类中任何整数属性的边界。但是,这并不能向该类的用户清楚地传达边界要求。我在这个问题上解决了一个类似的问题:

基于这个问题和从中获得的经验,我建议您创建一个新的BoundedInteger类。这个类将有一个value属性,它应该是自解释的。它还具有与integer之间的隐式转换,以便于类的用户使用。您还可以将MinValue和MaxValue项添加为只读属性,并将它们作为必需参数包含在类构造函数中

一个重要的补充是,您可能并不总是希望在错误的分配上抛出异常,因为有时错误的分配可能并不那么例外。根据上下文的不同,在尝试错误分配时,可以选择以下几种行为:

无论如何都允许赋值例如:某人可能真的想要110%的值 保留以前的值 重置为零或其他一些默认值 将该值设置为最接近的界限,即,如果他们尝试将110指定为百分比,则将其设置为100 根据属性的需要,这些行为中的任何一个都可能抛出异常或不抛出异常。根据您的问题域,这可能有些过分,但在您设计程序时值得记住


如果您决定需要这种灵活性,则需要在枚举中定义这些行为,并使用只读属性来保存该值。然后,选择一个作为默认值,然后添加一个额外的构造函数,您可以在其中设置该实例的特定行为以及是否应引发异常。最后,如果您可能会允许错误的赋值,那么您需要提供一个IsValid方法来测试边界属性。

当然,您可以通过在setter中检查来对类中的任何整数属性强制执行边界。但是,这并不能向该类的用户清楚地传达边界要求。我在这个问题上解决了一个类似的问题:

基于这个问题和从中获得的经验,我建议您创建一个新的BoundedInteger类。这个类将有一个value属性,它应该是自解释的。它还具有与integer之间的隐式转换,以便于类的用户使用。您还可以将MinValue和MaxValue项添加为只读属性,并将它们作为必需参数包含在类构造函数中

一个重要的补充是,您可能并不总是希望抛出异常 在糟糕的任务上,因为有时候糟糕的任务可能并不那么例外。根据上下文的不同,在尝试错误分配时,可以选择以下几种行为:

无论如何都允许赋值例如:某人可能真的想要110%的值 保留以前的值 重置为零或其他一些默认值 将该值设置为最接近的界限,即,如果他们尝试将110指定为百分比,则将其设置为100 根据属性的需要,这些行为中的任何一个都可能抛出异常或不抛出异常。根据您的问题域,这可能有些过分,但在您设计程序时值得记住


如果您决定需要这种灵活性,则需要在枚举中定义这些行为,并使用只读属性来保存该值。然后,选择一个作为默认值,然后添加一个额外的构造函数,您可以在其中设置该实例的特定行为以及是否应引发异常。最后,如果您可能会允许错误的赋值,那么您需要提供一个IsValid方法来测试边界属性。

这可以利用IComparable使其更通用,请参阅我的回答中我的RestrictedRange实现,以避免类的引用语义带来意外,作为一个结构,这可能更好。利用IComparable,这可以变得更通用,请参阅我的回答中我的RestrictedRange实现。为了避免类的引用语义带来意外,作为一个结构,这可能更好。