【问题标题】:Force a Class's float variable to be within range强制类的浮点变量在范围内
【发布时间】:2022-03-06 03:28:22
【问题描述】:

如何强制类的变量可以设置在特定的数值范围内?例如,在下面的示例代码中,我想强制用户只能为变量 DownsamplingScale 设置 0.0f 到 1.0f 之间的值。

public sealed class DownsampleData
{
    public float DownsamplingScale = 0.0f;
}

我不是在寻找Clamping type solution,因为我真的需要告诉班级用户他/她必须设置一个 0.0f1.0f 范围内的值strong> 在他们使用我的课程时(编写代码,即在编译之前)。

有几种方法可以在运行时处理这种情况。我需要在编译期间/之前告知预期范围的信息。

【问题讨论】:

  • 如果设置字段/属性的代码接收到一个double 值作为它的自己的 方法参数,你希望它在编译时如何工作?从根本上说,不,没有办法做到这一点。
  • 只要您能够对常量执行此操作没问题,您就可以编写自己的自定义 Roslyn 分析器。但是,对于像downsampleData.DownsamplingScale = 1f; downsampleData.DownsamplingScale *= 2 这样的非平凡场景,这当然会很快失败。这种事情在编译时无法检测到,必须通过属性来处理。
  • 是否可以选择使用整数类型参数,将其缩放到您想要的范围?
  • 出于我的兴趣,为什么在编译时,我的意思是属性设置器检查解决方案会在他们尝试运行它时停止他们的应用程序
  • @Progman:只要值在0.0f1.0f 的范围内,任何数据类型都可以工作(包括自定义结构/类)。

标签: c#


【解决方案1】:

我需要在编译期间/之前告知预期范围的信息。

编译器不可能做到这一点。该值可能是从文件中读取的,并且该文件在编译时甚至可能不存在,例如

var d = new DownsampleData();
d.DownsamplingScale(float.Parse(File.ReadAllText("file_on_customer_pc_only.dat")));

【讨论】:

  • enums的情况下我们是不是也有类似的情况。这些值只能从提供的选项中设置。我基本上需要一些介于 0.0f 到 1.0f 之间的值的枚举,并寻找一些聪明的方法来做到这一点。
  • @skm: "这些值只能从提供的选项中设置。" - 不,您可以将基础基类型的任何值转换为枚举类型。例如:FileMode fm = (FileMode) 1123456;。所以是的,我们有类似的情况 - 你不能依赖枚举值实际上只是命名值之一。
  • @JonSkeet:当然,我只是想澄清我的要求。例如,如果我们有一个这样的颜色枚举enum Color {Red, Green},至少用户会知道在编写代码时他/她应该选择这两个值之一。同样,我想在编写代码时(即编译前/编译期间)通知此人。如果有人真的想打破,没关系!顺便说一句,变量不能是浮点类型。对我来说,只有值(0.0f1.0f 之间)很重要。
  • @skm: 如果用户收到Color 类型的参数怎么办?如果没有额外的验证,他们仍然不知道它将是红色还是绿色。听起来您可能想引入自己的不可变 struct,其中包含在构造上经过验证的 float 字段。但从根本上说,如果以某种方式从磁盘读取值(根据 Thomas 的示例),我仍然看不到您希望在编译时如何处理它。 处理编译时常量对 IMO 的好处非常有限。
  • @JonSkeet 当然,我还必须进行运行时检查,我会这样做。在运行时,我可以抛出异常等,我已经知道如何做到这一点,因此没有提出问题。如果有人在设置硬编码值(例如初始化),我不知道如何在编译之前/期间“也”通知。
【解决方案2】:

您可以创建参数为无符号整数类型的属性(或方法)。您可以根据需要的精度选择实际类型。如果你使用

public byte DownsamplingScaleFactor {get; set;}

您将有 256 个值可供选择。从文档中可以清楚地看出,值 0 表示“0%”,255 表示“100%”。由于所选类型仅支持这些范围,因此无法使用任何更低或更高的值。

使用 byte 类型,您将获得 1/256 的精度(忽略逐个问题)。如果您需要更高的精度,请使用任何其他无符号整数类型,例如 ushortuintulong

【讨论】:

  • 在这里扮演魔鬼的拥护者:如果您使用float,则可以有更高的精度,并指出值float.MinValue表示0%,float.MaxValue表示100%。问题解决了! ...对于“已解决”的某些值。 (当然,float 比其他类型更不太适合,因为外端的精度会降低,但你明白我的意思。)
猜你喜欢
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-25
  • 2022-11-12
  • 2012-07-07
相关资源
最近更新 更多