I am confused about what is wrong here:
public static T? GetValue<T>(this JObject o, string propertyName)
{
JToken? jtok = o.GetValue(propertyName);
return jtok?.ToObject<T>();
}
I get:
error CS0023: Operator '?' cannot be applied to operand of type 'T'
(in the ?.
)
What is wrong here ? GetValue
returns JToken?
not T
CodePudding user response:
Because you didn't specify the T is a class (reference type) or a struct (non-nullable value type), the ?=
operator couldn't know which type to promote.
You can modify it as where T : class
to solve the problem (in your case I think T
would be a class.)
For more detailed explanation including what would be the exact codes generated by ?=
operator, you can check the existing question:
null-conditional operator doesn't work with Func<T> inside a generic method
CodePudding user response:
Compiler throws error because you are trying to return something as null which you already constrainted as notnull, which means you telling compiler that T will never ever be null and the same time you also expecting that T might be become null in the future at some point. And Here is alternative solution without compiler error and same logic
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;
}
or here is the same with more elegant syntax
public static T GetValue<T>(this JObject o, string propertyName) where T : notnull
=> o.TryGetValue(propertyName, out JToken jtok) ? jtok.ToObject<T>() : default;
Ask in comments if you don't understand the code
EDIT After 1st comment:
Now(after you deleted notnull
constraint) your code telling compiler that T could be anything(value(notNullable) or reference(nullable) type) so when you are checking jtok
with ?.
you are telling compiler that at some point it should expect null value, which if T will be for example int will be error, because you can't just assign null to int directly
consider this use case of your code int i = sampleObj.GetValue<int>("EXAMPLE");
. In this case if "EXAMPLE" property does not exist you are forcing compiler to assign null to int, but compiler is clever and it's throwing that error to protect you from that error