C
C#10mo ago
LazyGuard

null!

I am receiving some infos from an API and I have to decerialize to a model I am doing somthing like
if (response.IsSuccess)
//deserialize to Person
else
// deserialize to ProblemDetails
if (response.IsSuccess)
//deserialize to Person
else
// deserialize to ProblemDetails
And in person I hava defined properties using public sting Name {get; set;} = null! Is the use of null! here a bad pratice ?
27 Replies
LazyGuard
LazyGuardOP10mo ago
I am asssuming that I will always have a Name in the response, if something happens and the API does change somehow it will result in an exception at runtime right ? I cannot be absoluetly sure about it being non null How to do better ? PS: t I have a lot more properties other than names How to do it in a scalable manner Any help ? 🙏
Pobiega
Pobiega10mo ago
generally with modern C# you'd use public required string Name {get; set;} instead
LazyGuard
LazyGuardOP10mo ago
yeah but we are not using that version in C# :/
Pobiega
Pobiega10mo ago
then its fine well, then use a constructor, or validate the model after deserialization
LazyGuard
LazyGuardOP10mo ago
but it's in the model that I have that null! so if I recevie a null in Name, it will throws as soon as the deserialization process right ?
Pobiega
Pobiega10mo ago
no thats not what that does :p null! isnt magical, its just "set the value to null, and ignore the nullability warning"
MODiX
MODiX10mo ago
Angius
REPL Result: Success
class Person
{
public string Name { get; set; } = null!;
}

var p = new Person();
class Person
{
public string Name { get; set; } = null!;
}

var p = new Person();
Compile: 293.246ms | Execution: 34.872ms | React with ❌ to remove this embed.
Pobiega
Pobiega10mo ago
that means if you deserialize something that doesnt set Name, it will still have the value of null.
Angius
Angius10mo ago
As you can see, no errors A person can be constructed without a name
LazyGuard
LazyGuardOP10mo ago
I am lost 😄 I thought the ! throws whith null :/
Pobiega
Pobiega10mo ago
no, its just a "ignore warning" thing it sounds like you really want some validation
LazyGuard
LazyGuardOP10mo ago
yes ^^'
Pobiega
Pobiega10mo ago
so add some validation, outside of the model 😛 I'm not a big fan of models validating themselves, but its possible json deserialization can support constructors, so you could do it there that'd be fine
LazyGuard
LazyGuardOP10mo ago
okay thanks ! by the way, what happen if there was a required there?
MODiX
MODiX10mo ago
Angius
REPL Result: Failure
class Person
{
public required string Name { get; set; } = null!;
}

var p = new Person();
class Person
{
public required string Name { get; set; } = null!;
}

var p = new Person();
Exception: CompilationErrorException
- Required member 'Person.Name' must be set in the object initializer or attribute constructor.
- Required member 'Person.Name' must be set in the object initializer or attribute constructor.
Compile: 265.622ms | Execution: 0.000ms | React with ❌ to remove this embed.
MODiX
MODiX10mo ago
Pobiega
REPL Result: Failure
class Person
{
public required string Name { get; set; }
}

var p = JsonSerializer.Deserialize<Person>("{}");
class Person
{
public required string Name { get; set; }
}

var p = JsonSerializer.Deserialize<Person>("{}");
Exception: CompilationErrorException
- 'JsonSerializer' is an ambiguous reference between 'Newtonsoft.Json.JsonSerializer' and 'System.Text.Json.JsonSerializer'
- 'JsonSerializer' is an ambiguous reference between 'Newtonsoft.Json.JsonSerializer' and 'System.Text.Json.JsonSerializer'
Compile: 298.224ms | Execution: 0.000ms | React with ❌ to remove this embed.
Pobiega
Pobiega10mo ago
Sigh Unhandled exception. System.Text.Json.JsonException: JSON deserialization for type 'Person' was missing required properties, including the following: Name thats what happens STJ respects required
LazyGuard
LazyGuardOP10mo ago
so to wrap up, the null! is a way to tell the compiler "it won't be null" . but if it happens to be null then nothing happens. Why not simply use string? there then it will have the same behaviour after all right ?
Pobiega
Pobiega10mo ago
null!, again, isnt magical its essentially a workaround for nullability its "make it null, but dont warn me about it, I know what I'm doing" if you WANT the property to be nullable, and wont guarantee otherwise, string? is the correct thing to do null! is what we used before required
Angius
Angius10mo ago
x! is a way of telling the compiler "trust me bro, I know x can be null, but it isn't, I swear on me mum" null! therefore, is telling the compilert "trust me bro, this null ain't null"
Pobiega
Pobiega10mo ago
and we all know swearing on your mum is a bad idea when you are lying
Angius
Angius10mo ago
Which shuts up its warnings about uninitialized property
LazyGuard
LazyGuardOP10mo ago
yeah but I mean who cares, at the end of the day, whether it was string and null! or string? it will have the same behaviour
Pobiega
Pobiega10mo ago
.. no? if you declare it as string?, then the consumer of your model will need to check for null before using the value thats what NRTs are for
LazyGuard
LazyGuardOP10mo ago
okay I see, I was only having this examples in head
class Person
{
public string Name { get; set; } = null!;
}

var p = new Person();
class Person
{
public string Name { get; set; } = null!;
}

var p = new Person();
class Person
{
public string? Name { get; set; };
}

var p = new Person();
class Person
{
public string? Name { get; set; };
}

var p = new Person();
i like chatgpt
i like chatgpt10mo ago
How about consuming legacy libraries where NRT has not been introduced, we still need to check non-nullable reference types too for null, right?
Pobiega
Pobiega10mo ago
non NRT libs can be treated as everything being nullable since that was the default
Want results from more Discord servers?
Add your server