C
C#4mo 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
LazyGuard4mo 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
Pobiega4mo ago
generally with modern C# you'd use public required string Name {get; set;} instead
LazyGuard
LazyGuard4mo ago
yeah but we are not using that version in C# :/
Pobiega
Pobiega4mo ago
then its fine well, then use a constructor, or validate the model after deserialization
LazyGuard
LazyGuard4mo 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
Pobiega4mo ago
no thats not what that does :p null! isnt magical, its just "set the value to null, and ignore the nullability warning"
MODiX
MODiX4mo 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
Pobiega4mo ago
that means if you deserialize something that doesnt set Name, it will still have the value of null.
Angius
Angius4mo ago
As you can see, no errors A person can be constructed without a name
LazyGuard
LazyGuard4mo ago
I am lost 😄 I thought the ! throws whith null :/
Pobiega
Pobiega4mo ago
no, its just a "ignore warning" thing it sounds like you really want some validation
LazyGuard
LazyGuard4mo ago
yes ^^'
Pobiega
Pobiega4mo 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
LazyGuard4mo ago
okay thanks ! by the way, what happen if there was a required there?
MODiX
MODiX4mo 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
MODiX4mo 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
Pobiega4mo 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
LazyGuard4mo 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
Pobiega4mo 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
Angius4mo 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
Pobiega4mo ago
and we all know swearing on your mum is a bad idea when you are lying
Angius
Angius4mo ago
Which shuts up its warnings about uninitialized property
LazyGuard
LazyGuard4mo 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
Pobiega4mo 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
LazyGuard4mo 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 chatgpt4mo 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
Pobiega4mo 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
More Posts