我有这个结构:
public struct MyValue
{
public string FirstPart { get; private set; }
public string SecondPart { get; private set; }
public static implicit operator MyValue(string fromInput)
{ // first breakpoint here.
var parts = fromInput.Split(new[] {'@'});
return new MyValue(parts[0], parts[1]);
}
public static implicit operator string(MyValue fromInput)
{ // second breakpoint here.
return fromInput.ToString();
}
public override string ToString()
{
return FirstPart + "@" + SecondPart;
}
public MyValue(string firstPart, string secondPart) : this()
{
this.FirstPart = firstPart;
this.SecondPart = secondPart;
}
}
我已根据上述评论设定了断点。
然后我这样做:
var first = new MyValue("first", "second");
if (first == (MyValue) null) throw new InvalidOperationException();
当它进入if (first == (MyValue) null)
时,我观察到一些奇怪的行为:第二个断点由于某种原因被击中。为什么尝试将MyValue
转换为字符串以进行简单的相等比较?
然后,如果我让代码继续,它会碰到第一个断点,现在我想知道为什么它试图转换一个字符串(值为null
尽管事实上我已明确地转换null
MyValue
MyValue
成if (first == (MyValue) null)
?使用像/* Dropdown Menu Trucks*/
$("#menu-main-menu .show-dropdown").hover(function(){
$("#dropdown").slideDown('fast');
});
$("#dropdown").mouseenter(function(){
$("#dropdown").show();
});
$("#dropdown").mouseleave(function(){
$("#dropdown").slideUp('fast');
});
// ----------------------------
/* Dropdown Menu Engines */
$("#menu-main-menu .show-dropdown2").hover(function(){
$(".dropdown-engines").slideDown('fast');
});
$(".dropdown-engines").mouseenter(function(){
$(".dropdown-engines").show();
});
$(".dropdown-engines").mouseleave(function(){
$(".dropdown-engines").slideUp('fast');
});
if ($('#dropdown').is(':visible')) {
$(".dropdown-engines").slideUp();
}
else if ($('.dropdown-engines').is(':visible')) {
$("#dropdown").slideUp();
}
这样的语句时不应该涉及字符串,那么这里实际发生了什么?
答案 0 :(得分:12)
忙于评论,问题就变得清晰了。
C#编译器无法编译(MyStruct) null
,但在你的情况下它会编译。
这是因为你有一个来自引用类型的隐式运算符(这种情况为string
)null
完全有效。
我认为你现在可以遵循为什么它以你看到的方式执行:)
PS:这是一个很好的例子,为什么'有损'一般不鼓励隐式算子。
答案 1 :(得分:7)
要完成@leppies answer,这是调用代码(发布模式):
public void X()
{
var first = new MyValue("first", "second");
if (first == (MyValue) null) throw new InvalidOperationException();
}
实际上编译的是:
public void X()
{
if (new MyValue("first", "second") == null)
{
throw new InvalidOperationException();
}
}
这是呼叫发出的IL:
// Methods
.method public hidebysig
instance void X () cil managed
{
// Method begins at RVA 0x20dc
// Code size 45 (0x2d)
.maxstack 8
IL_0000: ldstr "first"
IL_0005: ldstr "second"
IL_000a: newobj instance void MyValue::.ctor(string, string)
IL_000f: call string MyValue::op_Implicit(valuetype MyValue)
IL_0014: ldnull
IL_0015: call valuetype MyValue MyValue::op_Implicit(string)
IL_001a: call string MyValue::op_Implicit(valuetype MyValue) <--- This!
IL_001f: call bool [mscorlib]System.String::op_Equality(string, string)
IL_0024: brfalse.s IL_002c
IL_0026: newobj instance void [mscorlib]System.InvalidOperationException::.ctor()
IL_002b: throw
IL_002c: ret
} // end of method C::X
正如您所看到的,在创建MyValue
的新实例后,操作IL_001a
调用隐式转换为string
,因为是编译器的唯一可能性使值类型比较null
实际编译。