Home > Back-end >  Error using Null-conditional operators in extension method [duplicate]
Error using Null-conditional operators in extension method [duplicate]

Time:09-21

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

  • Related