我是C#的新手,在探索语言功能时,我遇到了一些奇怪的事情:
struct Foo
{
public Foo Identity() { return this; }
public static void Bar(Foo? foo)
{
Foo foo1 = foo?.Identity().Value; // Does not compile
Foo foo2 = (foo?.Identity()).Value; // Compiles
}
}
有人可以向我解释为什么需要括号吗?
答案 0 :(得分:40)
有人可以向我解释为什么需要括号吗?
因为Identity()
返回Foo
(不是Foo?
),因此没有Value
属性。如果foo
为空,则null将通过Identity
调用传播。
当你在它周围添加括号时,表达式的结果是Nullable<Foo>
,其中 具有Value
属性。
另请注意,如果foo
为null,那么您将在没有值的Value
上调用Nullable<Foo>
,并将获得异常< em>在运行时。一些静态分析器会识别出您可能存在等待发生的空引用异常,并向您发出警告。
如果将它们扩展为等效而没有空传播,则会更清楚:
Foo foo1;
if(foo != null)
{
foo1 = foo.Identity().Value; // not possible - Foo has no Value property.
}
else
{
foo1 = null; // also not possible
}
Foo foo2;
Foo? temp;
if(foo != null)
{
temp = foo.Identity();
}
else
{
temp = null; // actually a Nullable<Foo> with no value
}
foo2 = temp.Value; // legal, but will throw an exception at run-time if foo is null
如果
Identity()
返回Foo
,为什么Foo foo3 = foo?.Identity();
无法编译?
相当于:
Foo foo3
if(foo != null)
{
foo3 = foo.Identity();
}
else
{
foo3 = null; // not possible
}
答案 1 :(得分:0)
我认为c#团队做出这样做是一个很好的决定。请考虑以下情况:
如果结构是:
struct Foo
{
public int ID { set; get; }
public Foo Identity() { return this; }
public static void Bar(Foo? foo)
{
int? foo1 = foo?.Identity().ID; // compile
Foo foo2 = (foo?.Identity()).Value; // Compiles
}
}
如果您不需要括号来访问Nullable结果,那么您将无法访问ID
属性。由于以下内容无法编译:
int? foo2 = (foo?.Identity()).GetValueOrDefault()?.ID
当您在foo?.Identity().
.
返回的Foo
类型Identity()
之后写下(foo?.Identity()).
时的内容。但是在.
Foo?
foo?.Identity().
之后的内容是整个陈述的实际结果{{1}}