1

Considering the following class:

public class Property
{
    public string StringValue { get; private set; }

    private Property(string value)
    {
        this.StringValue = value;
    }
}

I am trying to write a TrySomething method (with nullable enabled). I first wrote something like that:

public bool TryGetValue<T>([NotNullWhen(true)] out T? value)
{
    value = JsonSerializer.Deserialize<T>(this.StringValue);

    return value != null;
}

When using such implementation with reference type, I get the CS8602 warning when writing the following code:

if (property.TryGetValue<Foo>(out var v))
{
    v.ToString(); // OK
}
else
{
    v.ToString(); // CS8602
}

But when writing it with value types, it does not:

if (property.TryGetValue<int>(out var v))
{
    v.ToString(); // OK
}
else
{
    v.ToString(); // OK
}

Is it possible to write such methods for value types?

7
  • 3
    How could v be null after int.TryParse(s, out var v)? int is a valuetype that cannot be null. So in the implementation of int.TryParse (and probably most of all those TrySomething<T>(out v)) there is some assigment like v = default(T). And in case of int, the default(int) is 0 and not null. So of course there is no CS8602, for variables of a value-type Commented Jan 27 at 15:37
  • And as a second remark: When writing a bool TrySomething(...) method, you should ensure it doesn't throw an exception. Never! Because that's be basic expection of anyone using such a Try... Only the boolean result should indicate whether the operation was successful or not. That's not the case for your TryGetValue, because JSON deserialization will throw an exception on an invalid JSON string Commented Jan 27 at 16:07
  • That's correct. The int.TryParse is indeed unrelevent. But still the implementation for value types does not trigger the warning (especially the first one). Commented Jan 27 at 16:10
  • "but still the implementation for value types does not trigger the warning" Why would it? value types cannot be null unless you explicitly specify them to be nullable Commented Jan 27 at 16:11
  • My first implementation explicitely specify a nullable type: bool TryGetValue<T>([NotNullWhen(true)] out T? value) Commented Jan 27 at 16:13

1 Answer 1

1

You need to provide "correct" type for your generic (and use Value instead ToString() to test the warning):

var property = ...;

if (!property.TryGetValue<int?>(out var i))
{
    var value = i.Value; // warning CS8629: Nullable value type may be null.
}

Demo @sharplab.io

Or constrain the generic parameter to value types:

public class Property
{   
    public bool TryGetValueType<T>([NotNullWhen(true)] out T? value) where T: struct
    {
        //...
    }
}

Demo @sharplab.io

The problem is indeed in using value types - for them T and T? for unconstrained generic types are treated as the same type (i.e. for you original implementation/call TryGetValue<int> T and T? both are int, so i.Value will not even compile) - see more in the answer for Nullability and generics in .NET 6

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.