我注意到在应用operator ==时,用户定义的隐式转换行为与用户定义的隐式转换到任意结构MyStruct的行为之间存在差异.
如果我有:
public struct IntA
{
public IntA(int value)
{ m_value = value; }
public static implicit operator int(IntA a)
{ return a.m_value; }
private int m_value;
}
public struct IntB
{
public IntB(int value)
{ m_value = value; }
public static implicit operator int(IntB b)
{ return b.m_value; }
private int m_value;
}
然后以下代码编译:
{
var a = new IntA(3);
var b = new IntB(4);
bool equal = (a == b); // ok! converted to int and used int operator==
// ...
}
这使用我的用户定义的隐式运算符int为IntA和IntB转换为int,然后调用operator ==(int,int).
但是,如果我有:
public struct MyStruct
{
public MyStruct(int value)
{ m_value = value; }
public static bool operator==(MyStruct lhs, MyStruct rhs)
{ return lhs.m_value == rhs.m_value; }
public static bool operator!=(MyStruct lhs, MyStruct rhs)
{ return lhs.m_value != rhs.m_value; }
private int m_value;
}
public struct MyStructA
{
public MyStructA(int value)
{ m_value = new MyStruct(value); }
public static implicit operator MyStruct(MyStructA a)
{ return a.m_value; }
private MyStruct m_value;
}
public struct MyStructB
{
public MyStructB(int value)
{ m_value = new MyStruct(value); }
public static implicit operator MyStruct(MyStructB b)
{ return b.m_value; }
private MyStruct m_value;
}
然后以下代码不编译:
{
var a = new MyStructA(3);
var b = new MyStructB(4);
bool equal = (a == b); // compile error: Operator `==' cannot be applied to operands of type `MyStructA' and `MyStructB'
// why can't it convert to MyStruct and use that operator==?
// ...
}
我希望它与前一个示例一样,并使用我的用户定义的隐式运算符MyStruct转换为MyStruct,然后调用operator ==(MyStruct,MyStruct).
它没有这样做.为什么不?从编译器的角度来看,这两种情况有什么不同?
最佳答案 答案在于语言规范.重点是我的.
C# Language Specification 7.3.4
An operation of the form x op y, where op is an overloadable binary
operator, x is an expression of type X, and y is an expression of type
Y, is processed as follows:
- The set of candidate user-defined operators provided by X and Y for the operation operator op(x, y) is determined. The set consists of
the union of the candidate operators provided by X and the candidate
operators provided by Y, each determined using the rules of §7.3.5.
If X and Y are the same type, or if X and Y are derived from a common
base type, then shared candidate operators only occur in the combined
set once.- If the set of candidate user-defined operators is not empty, then this becomes the set of candidate operators for the operation. Otherwise, the predefined binary operator op implementations, including their lifted forms, become the set of candidate operators
for the operation. The predefined implementations of a given
operator are specified in the description of the operator (§7.8
through §7.12). For predefined enum and delegate operators, the
only operators considered are those defined by an enum or delegate
type that is the binding-time type of one of the operands.- The overload resolution rules of §7.5.3 are applied to the set of candidate operators to select the best operator with respect to the
argument list (x, y), and this operator becomes the result of the
overload resolution process. If overload resolution fails to select a
single best operator, a binding-time error occurs.
因此,如果没有初始匹配,它会将所有内部定义的==运算符视为候选.因为有一个用于int,而不是MyStruct,所以你会看到不同的行为.