1

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

kofifus
  • 17,260
  • 17
  • 99
  • 173

2 Answers2

2

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

Yanger Yang
  • 121
  • 4
1

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

Chestera
  • 667
  • 2
  • 13
  • 22
  • I removed the `not null` (see edited question), error is still there – kofifus Sep 21 '21 at 02:23
  • edited and hope answer is understandable – Chestera Sep 21 '21 at 02:33
  • OK I see now ... I can solve it more cleanly like this: `public static T? GetValue(this JObject o, string propertyName) where T : class => o.GetValue(propertyName)?.ToObject();` can you pls add that to your answer ? then I'll mark it – kofifus Sep 21 '21 at 02:51
  • @kofifus one can't answer the question that way because the question does not put any constraint on the `T`... – Alexei Levenkov Sep 21 '21 at 02:53
  • @kofifus, Idk. if you will never need to pass value type into your implemented method then it's okay – Chestera Sep 21 '21 at 02:58