我认为db.collection.update(
{_id : ObjectId('592eae9a92e32cc41c1c9af7')},
{
$set : {
'source.2.2': 'c'
}
}
);
只是T?
的编译器简写。根据{{3}}:
语法
Nullable<T>
是T?
的简写,其中Nullable<T>
是值类型。 这两种形式是可以互换的。
然而,有一点(微不足道)的差异:Visual Studio不允许我在短线上调用静态方法:
T
为什么呢?这种限制有什么理由吗?
答案 0 :(得分:12)
您的MSDN引用回应了C#5.0规范的§4.1.10:
可空类型写为
T?
,其中T
是基础类型。此语法是System.Nullable<T>
的简写,这两种形式可以互换使用。
但“可互换”是过于简单化。确实T?
表示System.Nullable<T>
,但正如您所发现的那样,您无法在T?
处使用System.Nullable<T>
。特别是,示例中的成员访问(第7.6.4节)类型需要简单名称(第7.6.2节):
[§7.6]主要表达式包括最简单的表达形式。</ p>
基本表达式:
初级无阵列创建表达式
阵列创建表达式初级无阵列创建表达式
字面
简单名称
括号的表达式
成员访问
...[§7.6.2] 简单名称的格式为
I
或格式I<A1, ..., AK>
,其中I
是单个标识符<A1, ..., AK>
是一个可选的 type-argument-list 。[§7.6.4] 成员访问的格式为
E.I
或格式为E.I<A1, ..., AK>
,其中E
为 primary-expression ,I
是单个标识符,<A1, ..., AK>
是可选的 type-argument-list 。
Nullable<T>
是简单名称而T?
不是,所以前者编译而后者不编译。
为什么C#语言设计人员需要成员访问表达式来使用简单名称而不是任何类型?我想只有他们可以肯定地说,但也许这个要求简化了语法:在表达式中,编译器可以假设?
始终是条件(三元)运算符,而不是可能的可空类型说明符。
事后看来,这是一个幸运的选择,它允许C#6.0添加?.
运算符而不会破坏现有程序。例如,考虑这个病态的例子:
struct S
{
public bool Equals(int x, int y) { return false; }
}
class C
{
public static void Main()
{
S? S = new S();
Console.WriteLine(S?.Equals(1, 1)); // "True" or "False"?
}
}
是否应将S?.Equals
解析为Nullable<S> . Equals
,调用类Equals
的{{1}}静态方法?或者应该将其解析为Object
,对变量S ?. Equals
的{{1}}实例方法进行空条件调用?由于Equals
不是简单名称,因此后者明确无误。
答案 1 :(得分:0)
虽然您对语法很正确,但可以使用Nullable类型作为参数从默认类型调用Equals方法。
您可以尝试使用您想要的任何值进行此单元测试:
int? i = 4;
int? j = null;
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j));