cin*_*nek 4 c# generics ternary-operator
谁能解释为什么此代码在使用?
运算符时会失败,但可以与if语句一起使用?
下面的代码编译没有错误。运行它时会引发异常。
var myClass = new MyClass<string>();
string tString;
//this works fine
if (myClass.HasValue)
{
tString = myClass;
}
else
{
tString = null;
}
//this throws Object reference not set to an instance of an object.
tString = myClass.HasValue ? myClass : null;
class MyClass<T>
{
private T value;
public T Value
{
get
{
if(value == null)
{
throw new Exception("Value cannot be null");
}
return value;
}
set { this.value = value; }
}
public static implicit operator T(MyClass<T> x)
{
return x.value;
}
public bool HasValue
{
get { return value != null; }
}
}
Run Code Online (Sandbox Code Playgroud)
can*_*on7 11
tString = myClass.HasValue ? myClass : null;
Run Code Online (Sandbox Code Playgroud)
在这里,我们有一个三元。三元数具有一个类型,该类型由两个参数确定。编译器查看myClass
和null
,发现它们是兼容的(它们都可以转换为MyClass<string>
),并确定三元类型为MyClass<string>
。
如果myClass.HasValue
为false
,则我们命中null
三元组的分支。然后,我们得到一个MyClass<string>
实例,它是null
。然后,我们需要将其转换为string
:,编译器会调用您的隐式运算符,但会传入null
。这会导致你的NullReferenceException
,因为你进入x.value
,但x
是null
。
不会发生这种情况,if/else
因为我们永远不会构造一个MyClass<string>
is null
。相反,我们null
直接分配给string
。
这个简单的示例由于相同的原因而导致相同的异常:
MyClass<string> myClass = null;
string s = myClass;
Run Code Online (Sandbox Code Playgroud)
通过执行以下操作,也可以通过强制三元类型为string
而不是来查看此情况MyClass<string>
:
tString = myClass.HasValue ? myClass : (string)null;
Run Code Online (Sandbox Code Playgroud)
要么
tString = myClass.HasValue ? (string)myClass : null;
Run Code Online (Sandbox Code Playgroud)
在这种情况下,不会发生异常。
OP指出,对于显式运算符不会发生这种情况。这是错误的:是的。
tString = (string)(myClass.HasValue ? myClass : null);
Run Code Online (Sandbox Code Playgroud)
由于相同的原因,这将引发相同的异常。
相反,如果您这样做:
tString = myClass.HasValue ? (string)myClass : null;
Run Code Online (Sandbox Code Playgroud)
然后你落入相同的情况下,我在前面所描述的,因为你永远不创建一个MyClass<string>
是空的,所以你从来没有尝试这种转换null
MyClass<string>
成一个string
。