在扩展方法中使用 Null 条件运算符时出错
Error using Null-conditional operators in extension method
我很困惑这里出了什么问题:
public static T? GetValue<T>(this JObject o, string propertyName)
{
JToken? jtok = o.GetValue(propertyName);
return jtok?.ToObject<T>();
}
我得到:
error CS0023: Operator '?' cannot be applied to operand of type 'T'
(在?.
)
这里有什么问题吗? GetValue
returns JToken?
不是 T
编译器抛出错误,因为你试图将你已经限制为 notnull 的东西 return 设为 null,这意味着你告诉编译器 T 永远不会为 null,同时你还期望 T 可能将来在某个时候变为空。
这是没有编译器错误和相同逻辑的替代解决方案
public static T GetValue<T>(this JObject o, string propertyName) where T : notnull
{
if (o.TryGetValue(propertyName, out JToken jtok))
return jtok.ToObject<T>();
else return default;
}
或者这里是一样的,语法更优雅
public static T GetValue<T>(this JObject o, string propertyName) where T : notnull
=> o.TryGetValue(propertyName, out JToken jtok) ? jtok.ToObject<T>() : default;
如果您不明白代码,请在评论中提问
编辑第一条评论后:
现在(删除 notnull
约束后)你的代码告诉编译器 T 可以是任何东西(值(不可空)或引用(可空)类型)所以当你检查 jtok
与 ?.
你告诉编译器在某些时候它应该期望空值,如果 T 是例如 int 将会出错,因为你不能直接将 null 分配给 int
考虑您的代码的这个用例 int i = sampleObj.GetValue<int>("EXAMPLE");
。在这种情况下,如果“EXAMPLE”属性 不存在,您将强制编译器将 null 分配给 int,但编译器很聪明,它会抛出该错误以保护您免受该错误的影响
因为您没有指定 T 是 class(引用类型)或结构(不可空值类型),所以 ?.
运算符无法知道要提升哪种类型.
您可以将其修改为where T : class
来解决问题(在您的情况下我认为T
将是class。)
更详细的解释,包括?.
运算符生成的确切代码是什么,您可以查看现有问题:
我很困惑这里出了什么问题:
public static T? GetValue<T>(this JObject o, string propertyName)
{
JToken? jtok = o.GetValue(propertyName);
return jtok?.ToObject<T>();
}
我得到:
error CS0023: Operator '?' cannot be applied to operand of type 'T'
(在?.
)
这里有什么问题吗? GetValue
returns JToken?
不是 T
编译器抛出错误,因为你试图将你已经限制为 notnull 的东西 return 设为 null,这意味着你告诉编译器 T 永远不会为 null,同时你还期望 T 可能将来在某个时候变为空。 这是没有编译器错误和相同逻辑的替代解决方案
public static T GetValue<T>(this JObject o, string propertyName) where T : notnull
{
if (o.TryGetValue(propertyName, out JToken jtok))
return jtok.ToObject<T>();
else return default;
}
或者这里是一样的,语法更优雅
public static T GetValue<T>(this JObject o, string propertyName) where T : notnull
=> o.TryGetValue(propertyName, out JToken jtok) ? jtok.ToObject<T>() : default;
如果您不明白代码,请在评论中提问
编辑第一条评论后:
现在(删除 notnull
约束后)你的代码告诉编译器 T 可以是任何东西(值(不可空)或引用(可空)类型)所以当你检查 jtok
与 ?.
你告诉编译器在某些时候它应该期望空值,如果 T 是例如 int 将会出错,因为你不能直接将 null 分配给 int
考虑您的代码的这个用例 int i = sampleObj.GetValue<int>("EXAMPLE");
。在这种情况下,如果“EXAMPLE”属性 不存在,您将强制编译器将 null 分配给 int,但编译器很聪明,它会抛出该错误以保护您免受该错误的影响
因为您没有指定 T 是 class(引用类型)或结构(不可空值类型),所以 ?.
运算符无法知道要提升哪种类型.
您可以将其修改为where T : class
来解决问题(在您的情况下我认为T
将是class。)
更详细的解释,包括?.
运算符生成的确切代码是什么,您可以查看现有问题: