为什么不能在 Nullable<T> 简写上调用静态方法?
Why is it impossible to call static methods on Nullable<T> shorthands?
我以为 T?
只是 Nullable<T>
的编译器 shorthand。根据MSDN:
The syntax T?
is shorthand for Nullable<T>
, where T
is a value type.
The two forms are interchangeable.
但是,有一点(微不足道的)区别:Visual Studio 不允许我在 shorthand 上调用静态方法:
bool b1 = Nullable<int>.Equals(1, 2); //no error
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'"
为什么?这个限制有什么原因吗?
虽然语法是正确的,但可以使用 Nullable 类型作为参数从默认类型调用 Equals 方法。
您可以使用您想要的任何值来尝试此单元测试:
int? i = 4;
int? j = null;
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j));
您的 MSDN 引用与 C# 5.0 规范的 §4.1.10 相呼应:
A nullable type is written T?
, where T
is the underlying type. This syntax is shorthand for System.Nullable<T>
, and the two forms can be used interchangeably.
但是“可互换”过于简单化了。 T?
确实意味着 System.Nullable<T>
,但正如您所发现的,您不能在可以使用 System.Nullable<T>
的所有地方使用 T?
。特别是,您示例中的 member-access(§7.6.4)类型需要 simple-name(§7.6.2):
[§7.6] Primary expressions include the simplest forms of expressions.
primary-expression:
primary-no-array-creation-expression
array-creation-expression
primary-no-array-creation-expression
literal
simple-name
parenthesized-expression
member-access
...
[§7.6.2] A simple-name is either of the form I
or of the form I<A1, ..., AK>
, where I
is a single identifier and <A1, ..., AK>
is an optional type-argument-list.
[§7.6.4] A member-access is either of the form E.I
or of the form E.I<A1, ..., AK>
, where E
is a primary-expression, I
is a single identifier and <A1, ..., AK>
is an optional type-argument-list.
Nullable<T>
是一个 简单名称 而 T?
不是,所以前者编译而后者不编译。
为什么 C# 语言设计者需要 member-access 表达式来使用 simple-name 而不是任何 类型?我想只有他们可以肯定地说,但也许这个要求简化了语法:在表达式中,编译器可以假定 ?
始终是条件(三元)运算符而不是可能为空的类型说明符。
但事后看来,这是一个幸运的选择,它允许 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
,调用classObject
的Equals
静态方法?还是应该解析为S ?. Equals
,对变量S
的Equals
实例方法的空条件调用?因为 S?
不是 单名 ,所以毫无疑问是后者。
我以为 T?
只是 Nullable<T>
的编译器 shorthand。根据MSDN:
The syntax
T?
is shorthand forNullable<T>
, whereT
is a value type. The two forms are interchangeable.
但是,有一点(微不足道的)区别:Visual Studio 不允许我在 shorthand 上调用静态方法:
bool b1 = Nullable<int>.Equals(1, 2); //no error
bool b2 = int?.Equals(1, 2); //syntax error "Invalid expression term 'int'"
为什么?这个限制有什么原因吗?
虽然语法是正确的,但可以使用 Nullable 类型作为参数从默认类型调用 Equals 方法。
您可以使用您想要的任何值来尝试此单元测试:
int? i = 4;
int? j = null;
Assert.AreEqual(Nullable<int>.Equals(i, j), int.Equals(i, j));
您的 MSDN 引用与 C# 5.0 规范的 §4.1.10 相呼应:
A nullable type is written
T?
, whereT
is the underlying type. This syntax is shorthand forSystem.Nullable<T>
, and the two forms can be used interchangeably.
但是“可互换”过于简单化了。 T?
确实意味着 System.Nullable<T>
,但正如您所发现的,您不能在可以使用 System.Nullable<T>
的所有地方使用 T?
。特别是,您示例中的 member-access(§7.6.4)类型需要 simple-name(§7.6.2):
[§7.6] Primary expressions include the simplest forms of expressions.
primary-expression:
primary-no-array-creation-expression
array-creation-expressionprimary-no-array-creation-expression
literal
simple-name
parenthesized-expression
member-access
...[§7.6.2] A simple-name is either of the form
I
or of the formI<A1, ..., AK>
, whereI
is a single identifier and<A1, ..., AK>
is an optional type-argument-list.[§7.6.4] A member-access is either of the form
E.I
or of the formE.I<A1, ..., AK>
, whereE
is a primary-expression,I
is a single identifier and<A1, ..., AK>
is an optional type-argument-list.
Nullable<T>
是一个 简单名称 而 T?
不是,所以前者编译而后者不编译。
为什么 C# 语言设计者需要 member-access 表达式来使用 simple-name 而不是任何 类型?我想只有他们可以肯定地说,但也许这个要求简化了语法:在表达式中,编译器可以假定 ?
始终是条件(三元)运算符而不是可能为空的类型说明符。
但事后看来,这是一个幸运的选择,它允许 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
,调用classObject
的Equals
静态方法?还是应该解析为S ?. Equals
,对变量S
的Equals
实例方法的空条件调用?因为 S?
不是 单名 ,所以毫无疑问是后者。