我有一个结构:
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
到/ Duration
的隐式转换,但<
和>
运算符不适合它。
c#是否只识别基元类型之间的转换?
答案 0 :(得分:3)
首先请注意,C#将允许在类型之间进行最多一次隐式的用户定义转换。
因此,当您比较Decibel
的两个实例时,编译器会发现它可以使用用户定义的隐式转换将Decibel
转换为要与之比较的double
。< / p>
但是,当您比较Duration
的两个实例时,编译器找不到任何可用于进行比较的单隐式转换。对于可以隐式转换类型的任何类型,编译器不会考虑任何用户定义的比较运算符。它只会查找可以隐式转换类型的任何类型的内置比较运算符。
因此,即使TimeSpan
提供了理论上可以使用的用户定义的比较运算符,编译器也不会使用隐式转换为TimeSpan
。
另请注意,即使TimeSpan
类提供了对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) ...