为什么我不能用T?作为 C# 中的泛型参数
Why I can't use T? as a generic parameter in C#
我在 .NET Core
控制台应用程序中使用 .NET
5。以下代码无法编译:
public class NullableClass<T?>
{
}
错误是:
Error CS1003 Syntax error, ',' expected.
我是否使用任何约束都没有关系。
但是这段代码可以编译:
[return: MaybeNull]
public static T? Find<T>(IEnumerable<T?> sequence, Func<T?, bool> predicate)
{
foreach (var element in sequence) {
if (predicate(element)) return element;
}
return default(T?);
}
当我声明Find<T?>
时我有同样的错误。
我在这里有什么不明白的地方?
如果您希望 T
成为可为 null 的引用类型,您应该为此使用 generic constraint:
where T : class?
The type argument must be a reference type, either nullable or
non-nullable. This constraint applies also to any class, interface,
delegate, or array type.
public class NullableClass<T> where T : class?
{
// code here
}
请注意,问号是约束的一部分 - class
(没有问号)也有一个约束,意思是“引用类型”,在 c# 8 或更高版本中意思是“non-nullable 引用类型".
您对在哪里可以使用类型感到困惑。
您不应该在此处use/write输入:
public class NullableClass< >
^^^
或此处:
public static T? Find< >(IEnumerable<T?> sequence, Func<T?, bool> predicate)
^^^
在句法上,这些地方是 type_parameters
。您应该在那里声明类型参数,而不是使用现有类型。 public class Foo<List<int>>
没有意义,对吧?
根据语言规范,这是 class declaration:
的语法
class_declaration
: attributes? class_modifier* 'partial'? 'class' identifier type_parameter_list?
class_base? type_parameter_constraints_clause* class_body ';'?
;
type_parameter_list
: '<' type_parameters '>'
;
type_parameters
: attributes? type_parameter
| type_parameters ',' attributes? type_parameter
;
type_parameter
: identifier
;
实际上,类型参数只是标识符,就像变量声明中的变量名一样。 T?
不是标识符。在 type_parameter_list
中,您只是声明此 class/method 将具有的类型参数。
现在让我们看看 使用的类型。
public static T? Find<T>(IEnumerable<T?> sequence, Func<T?, bool> predicate)
^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
这些都是类型,所以你可以在那些地方使用T?
。方法 return type 显然是一个类型,所以你可以在那里使用一个类型。我上面标记的<>
是一个类型的一部分,所以它们是type_argument_list
,而不是type_parameter_list
。您可以在 type_argument_list
s:
中使用类型
type_name
: namespace_or_type_name
;
namespace_or_type_name
: identifier type_argument_list?
| namespace_or_type_name '.' identifier type_argument_list?
| qualified_alias_member
;
type_argument_list
: '<' type_arguments '>'
;
type_arguments
: type_argument (',' type_argument)*
;
type_argument
: type
;
如果要允许将可空引用类型和 non-nullable 引用类型用作类型参数 T
的类型参数,请使用 class?
constraint:
class NullableClass<T> where T: class? { ... }
Upvote Sweeper,如果你想使用可为 null 的类型,则不需要 ?关于定义,即
class Program
{
static void Main(string[] args)
{
int?[] valueList = new int?[] { 1, null, 3, 4, 5, null };
int? val = NullableClass<int?>.Find(valueList, new Func<int?, bool>(test));
}
public static bool test(int? testMe)
{
// Do something productive here
if (testMe != null && testMe % 2 == 0)
return true;
return false;
}
}
class NullableClass<T> {
public static T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)
{
foreach (var element in sequence)
{
if (predicate(element)) return element;
}
return default(T);
}
}
我在 .NET Core
控制台应用程序中使用 .NET
5。以下代码无法编译:
public class NullableClass<T?>
{
}
错误是:
Error CS1003 Syntax error, ',' expected.
我是否使用任何约束都没有关系。
但是这段代码可以编译:
[return: MaybeNull]
public static T? Find<T>(IEnumerable<T?> sequence, Func<T?, bool> predicate)
{
foreach (var element in sequence) {
if (predicate(element)) return element;
}
return default(T?);
}
当我声明Find<T?>
时我有同样的错误。
我在这里有什么不明白的地方?
如果您希望 T
成为可为 null 的引用类型,您应该为此使用 generic constraint:
where T : class?
The type argument must be a reference type, either nullable or non-nullable. This constraint applies also to any class, interface, delegate, or array type.
public class NullableClass<T> where T : class?
{
// code here
}
请注意,问号是约束的一部分 - class
(没有问号)也有一个约束,意思是“引用类型”,在 c# 8 或更高版本中意思是“non-nullable 引用类型".
您对在哪里可以使用类型感到困惑。
您不应该在此处use/write输入:
public class NullableClass< >
^^^
或此处:
public static T? Find< >(IEnumerable<T?> sequence, Func<T?, bool> predicate)
^^^
在句法上,这些地方是 type_parameters
。您应该在那里声明类型参数,而不是使用现有类型。 public class Foo<List<int>>
没有意义,对吧?
根据语言规范,这是 class declaration:
的语法class_declaration
: attributes? class_modifier* 'partial'? 'class' identifier type_parameter_list?
class_base? type_parameter_constraints_clause* class_body ';'?
;
type_parameter_list
: '<' type_parameters '>'
;
type_parameters
: attributes? type_parameter
| type_parameters ',' attributes? type_parameter
;
type_parameter
: identifier
;
实际上,类型参数只是标识符,就像变量声明中的变量名一样。 T?
不是标识符。在 type_parameter_list
中,您只是声明此 class/method 将具有的类型参数。
现在让我们看看 使用的类型。
public static T? Find<T>(IEnumerable<T?> sequence, Func<T?, bool> predicate)
^^ ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
这些都是类型,所以你可以在那些地方使用T?
。方法 return type 显然是一个类型,所以你可以在那里使用一个类型。我上面标记的<>
是一个类型的一部分,所以它们是type_argument_list
,而不是type_parameter_list
。您可以在 type_argument_list
s:
type_name
: namespace_or_type_name
;
namespace_or_type_name
: identifier type_argument_list?
| namespace_or_type_name '.' identifier type_argument_list?
| qualified_alias_member
;
type_argument_list
: '<' type_arguments '>'
;
type_arguments
: type_argument (',' type_argument)*
;
type_argument
: type
;
如果要允许将可空引用类型和 non-nullable 引用类型用作类型参数 T
的类型参数,请使用 class?
constraint:
class NullableClass<T> where T: class? { ... }
Upvote Sweeper,如果你想使用可为 null 的类型,则不需要 ?关于定义,即
class Program
{
static void Main(string[] args)
{
int?[] valueList = new int?[] { 1, null, 3, 4, 5, null };
int? val = NullableClass<int?>.Find(valueList, new Func<int?, bool>(test));
}
public static bool test(int? testMe)
{
// Do something productive here
if (testMe != null && testMe % 2 == 0)
return true;
return false;
}
}
class NullableClass<T> {
public static T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)
{
foreach (var element in sequence)
{
if (predicate(element)) return element;
}
return default(T);
}
}