使用 < 和 > 运算符时支持哪些隐式转换?
What implicit conversions are supported when using < and > operators?
我有一个结构:
public struct Decibel
{
public readonly double Value;
public Decibel (double value)
{
Value = value;
}
public static implicit operator Decibel (double decibels)
{
return new Decibel (decibels);
}
public static implicit operator double (Decibel decibels)
{
return decibels.Value;
}
}
现在我可以做到:
bool x = new Decibel (0) < new Decibel (1);
编译器似乎很聪明,可以将Decibel
转换为double
,然后使用<
运算符进行双精度运算?
我有不同的 struct
命名为 Duration
,它正在包装 TimeSpan
。它对 TimeSpan
to/from Duration
进行了隐式转换,但 <
和 >
运算符对其不起作用。
c#是否只识别原始类型之间的转换?
首先请注意,C# 最多允许在类型之间进行一次隐式用户定义转换。
因此,当您比较 Decibel
的两个实例时,编译器发现它可以使用用户定义的隐式转换将 Decibel
转换为 double
以进行比较.
然而,当您比较 Duration
的两个实例时,编译器无法找到任何可以用来进行比较的 单一 隐式转换。对于可以隐式转换为的任何类型,编译器不会考虑任何用户定义的比较运算符。它只会为类型可以隐式转换为的任何类型寻找内置比较运算符。
因此,即使 TimeSpan
提供了理论上可以使用的用户定义比较运算符,编译器也不会使用隐式转换为 TimeSpan
。
另请注意,即使 TimeSpan
class 提供了到 double
的隐式转换,编译器仍不会使用它,因为它最多只考虑一个隐式用户-在隐式转换链中定义转换。
换句话说,给定这些结构:
public struct Number
{
public readonly double Value;
public Number(double value)
{
Value = value;
}
public static implicit operator Number(double duration)
{
return new Number(duration);
}
public static implicit operator double(Number number)
{
return number.Value;
}
}
public struct NumberWrapper
{
public readonly Number Value;
public NumberWrapper(Number value)
{
Value = value;
}
public static implicit operator NumberWrapper(Number duration)
{
return new NumberWrapper(duration);
}
public static implicit operator Number(NumberWrapper number)
{
return number.Value;
}
}
此代码将编译:
bool x = new Number(1) < new Number(2);
当然会这样:
Number n1 = new NumberWrapper(1);
Number n2 = new NumberWrapper(2);
bool z = n1 < n2;
但这不会:
bool y = new NumberWrapper(1) < new NumberWrapper(2);
因为 NumberWrapper
没有隐式转换到任何支持 <
的类型而无需任何进一步的隐式转换。
请注意,所有基本数字和枚举类型(例如 char、short、int、long、float、double、decimal、enum)都提供内置比较运算符。所有其他类型只能提供用户定义的比较运算符。
用户定义的比较运算符如下所示:
public static bool operator < (MyType lhs, MyType rhs) ...
我有一个结构:
public struct Decibel
{
public readonly double Value;
public Decibel (double value)
{
Value = value;
}
public static implicit operator Decibel (double decibels)
{
return new Decibel (decibels);
}
public static implicit operator double (Decibel decibels)
{
return decibels.Value;
}
}
现在我可以做到:
bool x = new Decibel (0) < new Decibel (1);
编译器似乎很聪明,可以将Decibel
转换为double
,然后使用<
运算符进行双精度运算?
我有不同的 struct
命名为 Duration
,它正在包装 TimeSpan
。它对 TimeSpan
to/from Duration
进行了隐式转换,但 <
和 >
运算符对其不起作用。
c#是否只识别原始类型之间的转换?
首先请注意,C# 最多允许在类型之间进行一次隐式用户定义转换。
因此,当您比较 Decibel
的两个实例时,编译器发现它可以使用用户定义的隐式转换将 Decibel
转换为 double
以进行比较.
然而,当您比较 Duration
的两个实例时,编译器无法找到任何可以用来进行比较的 单一 隐式转换。对于可以隐式转换为的任何类型,编译器不会考虑任何用户定义的比较运算符。它只会为类型可以隐式转换为的任何类型寻找内置比较运算符。
因此,即使 TimeSpan
提供了理论上可以使用的用户定义比较运算符,编译器也不会使用隐式转换为 TimeSpan
。
另请注意,即使 TimeSpan
class 提供了到 double
的隐式转换,编译器仍不会使用它,因为它最多只考虑一个隐式用户-在隐式转换链中定义转换。
换句话说,给定这些结构:
public struct Number
{
public readonly double Value;
public Number(double value)
{
Value = value;
}
public static implicit operator Number(double duration)
{
return new Number(duration);
}
public static implicit operator double(Number number)
{
return number.Value;
}
}
public struct NumberWrapper
{
public readonly Number Value;
public NumberWrapper(Number value)
{
Value = value;
}
public static implicit operator NumberWrapper(Number duration)
{
return new NumberWrapper(duration);
}
public static implicit operator Number(NumberWrapper number)
{
return number.Value;
}
}
此代码将编译:
bool x = new Number(1) < new Number(2);
当然会这样:
Number n1 = new NumberWrapper(1);
Number n2 = new NumberWrapper(2);
bool z = n1 < n2;
但这不会:
bool y = new NumberWrapper(1) < new NumberWrapper(2);
因为 NumberWrapper
没有隐式转换到任何支持 <
的类型而无需任何进一步的隐式转换。
请注意,所有基本数字和枚举类型(例如 char、short、int、long、float、double、decimal、enum)都提供内置比较运算符。所有其他类型只能提供用户定义的比较运算符。
用户定义的比较运算符如下所示:
public static bool operator < (MyType lhs, MyType rhs) ...