kmo*_*ote 11 c# implicit-conversion explicit-conversion
我从另一个问题(稍加修改)中借用了以下代码,以便在我的代码中使用:
internal class PositiveDouble
{
private double _value;
public PositiveDouble(double val)
{
if (val < 0)
throw new ArgumentOutOfRangeException("Value needs to be positive");
_value = val;
}
// This conversion is safe, we can make it implicit
public static implicit operator double(PositiveDouble d)
{
return d._value;
}
// This conversion is not always safe, so we're supposed to make it explicit
public static explicit operator PositiveDouble(double d)
{
return new PositiveDouble(d); // this constructor might throw exception
}
}
Run Code Online (Sandbox Code Playgroud)
这段代码的原作者正确地遵守了MSDN的隐式和显式文档中给出的警告,但这里是我的问题:在潜在的特殊代码中是否explicit总是必要的?
所以,我的代码中有一些类型(例如"Volume")派生自PositiveDouble,我希望能够像下面的第一行一样方便地设置实例:
Volume v = 10; //only allowed by implicit conversion
Volume v = new Volume(10) //required by explicit conversion, but gets messy quick
Run Code Online (Sandbox Code Playgroud)
被迫在任何地方使用显式强制转换都会使代码的可读性降低.它如何保护用户?在我的程序的语义中,我从不期望卷是负面的; 事实上,如果它发生了,我希望抛出异常.因此,如果我使用隐式转换并抛出,那么"意外结果"可能会破坏我吗?
Cod*_*ter 14
C#语言规范在10.10.3转换运算符下说:
如果用户定义的转换可能引起异常(例如,因为源参数超出范围)或信息丢失(例如丢弃高位),则应将该转换定义为显式转换.
另外,从MSDN:implicit(C#Reference):
通常,隐式转换运算符不应该抛出异常并且永远不会丢失信息,以便在没有程序员意识的情况下可以安全地使用它们.如果转换运算符不符合这些条件,则应将其标记为显式.
考虑到这一点,你operator PositiveDouble(double d) 不应该被标记implicit,因为Volume v = -1会抛出异常.
所以回答你的问题:
在潜在的特殊代码中是否总是必需的?
不,这没有必要,但它应该.
基于意见的边界:如果您的代码是使用此转换的唯一代码,并且您发现隐式转换更易于阅读和/或维护,请随意使用它.
至于
它如何保护用户?
请参阅MSDN:explicit(C#参考)提及:
如果转换操作可能导致异常或丢失信息,则应将其标记为显式.这可以防止编译器以可能无法预料的后果静默调用转换操作.
当发生这种情况时,我无法理解,但是,如果你认为你的代码中的任何地方都不会从负双重转换,那么这不应该抛出.
cdh*_*wie 13
转换只有在总是成功时才应该隐含.如果它们可能失败或导致信息丢失,它们应该是明确的,因为这要求转换操作的调用者有意地表明他们想要这种转换,因此准备处理结果,无论可能是什么.
我们可以在框架中看到这个原始数值类型; 将inta 分配给a long是隐式转换,因为它总是会成功获得预期的结果.另一种方式可能导致OverflowException检查上下文,并且可能导致在未经检查的上下文中截断(丢失信息),因此您需要通过显式转换来指示您打算进行此转换.