For example, if I change the following data type bool?
[ProtoMember(10)]
public bool? HasEmail { get; set; }
to bool. Will it be a breakchange?
[ProtoMember(10)]
public bool HasEmail { get; set; }
The the logic to write HasEmail has been changed with ...?? false so it will never be null in the future.
The data will be stored in Redis. And some other program may try to read it using type bool? or bool.
Yes, this will be fine in the forwards direction; any previously missing data will now report as false via omission. However: you should note that if you serialize data from the new code, false values will be omitted, so will report as null (not false) if deserialized via any systems still using the old version.
This question already has answers here:
How to use .NET reflection to check for nullable reference type
(6 answers)
Closed 2 years ago.
Let's say I have an configuration or DTO object with use of C# nullable reference object feature:
public class ServiceConfig
{
public string ConnectionString { get; set; }
public string? OptionalComment { get; set; }
}
With upper code I get compiler warning "CS8618: Non-nullable property 'ConnectionString' must contain a non-null value when exiting constructor. Consider declaring the property as nullable." Because this objects needs parameterless constructor I can add = null! to get rid of the warning. But the problem is that object can still contain property with null value. Because I want to use this in a context of configuration and DTO's, there is an option to validate objects (in deserialization process) before they are passed to "real" objects.
How can I do it? It there a way where I can validate if object is valid by "Nullable references" notation? I see other option also with Data Annotations, but I use of this C# feature is a lot more attractive.
So, in fantasy I would like to have something like this:
public class ServiceConfig
{
public string ConnectionString { get; set; } = null!;
public string? OptionalComment { get; set; }
}
public class Deserializer
{
public static ServiceConfig Deserialize(string data)
{
var result = Json.Deserialize<ServiceConfig>(data);
var isObjectValid = result.IsValid(); // I want method something like this
if (!isObjectValid) throw new Exception("Deserialization error");
return result;
}
}
As per the docs # https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references
The compiler doesn't add any null checks or other runtime constructs
in a nullable context. At runtime, a nullable reference and a
non-nullable reference are equivalent.
So, when a DTO is deserialized at runtime, you may not have any additional constructs to denote whether a field is Nullable reference type or non-nullable reference type at atleast at the time of writing this answer.
It seems that doesn't need to declare get setter explicitely, so you can declare the public member by any default value, and let the compiler doing its job for you perfectly. :D
public string ConnectionString = null;
I have a viewmodel with a property defined like so:
public decimal decProperty { get; set; }
I have found this enforced "required" validation when I would like to allow nulls. To me specifying 0.00 is explicitly different to null ie the user is stating that the value is 0.00 while the latter means that the value is n/a.
The only way around this that I have found is to redefine the property as a string with regex validation:
[RegularExpression(#"\d+(\.\d{1,2})?", ErrorMessage = "Invalid decimal")]
public string strProperty { get; set; }
I am correct in my thinking and solution?
Thanks in advance.
A decimal property cannot ever be null though, try decimal? instead:
public decimal? decProperty { get; set; }
You could use a nullable decimal:
public decimal? decProperty { get; set; }
Doing so, if the user doesn't provide any value for the decProperty, it's value would be null. Otherwise, it would contain the value that the user provided.
This cannot be done with decimal, because null is not a valid decimal value. On the other hand a nullable decimal can has a a value the null or any valid decimal value.
If you want to read more about nullable types, please have a look here.
This question already has answers here:
Why type "int" is never equal to 'null'?
(8 answers)
Closed 9 years ago.
I am trying to compare the following:
if (e.CreatedBy == null)
But this is giving me an error saying:
The result of the expression is always 'false' since a value of type
'int' is never equal to 'null' of type 'int?'
Can someone help tell me how I can check if the value of CreatedBy has not been set yet? Note here's the definition of CreatedBy:
public int CreatedBy { get; set; }
int is a value type which means it can never be null. Its default value is 0. If you want store null instead of 0, you need to change the type to int?, which is a nullable int type. To read more about Nullable types, check "Nullable Types (C#)"
The type of CreatedBy is int which is a type that cannot take the value null.
From what you currently have, it is not possible to detect whether or not CreatedBy has been set. Suppose that its default value is 0. Then the value is set to 1, and then back to 0. Now, how can you distinguish the current 0 from the original unmodified 0?
If what you want to do is detect whether or not the value is 0, well I don't think I need to tell you how to do that. If you really want to detect whether or not the value has ever been set you'll need to maintain a bool flag and set that flag the first time the property's setter executes.
The int value is a type of non Nullable types see
http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.80).aspx
if you want to check if set or not use
//GetValueOrDefault()
private int? createdBy;
public int CreatedBy
{
get { return createdBy.GetValueOrDefault(-1); }
set { createdBy= value; }
}
///your code
if(e.CreatedBy == -1)
{
//not set
}else
{
//set
}
int is a value type which can't be null. If you want to make a value type nullable, you need to use int? which is a shorthand way of creating a Nullable object like this
Nullable<int> myNullable = new Nullable<int>();
Can someone help tell me how I can check if the value of CreatedBy has not been set yet?
No, that is impossible since value types (like int) can't be null.
But you can use Nullable Types which let's you declare it as a "Nullable of int" and then it can be null.
From the documentation I linked to:
A nullable type can represent the correct range of values for its underlying value type, plus an additional null value
To make your property a "Nullable of int", just add a questionmark:
public int? CreatedBy { get; set; }
The above syntax is actually just a shorthand for:
public Nullable<int> CreatedBy { get; set; }
Because default value of int is 0 not null. e.CreatedBy never going to have the value like null so better is to compare it with 0.
if (e.CreatedBy == 0)
nullable int can be equal to null but not nullable (default int) never going to be equal of null.
Well you are using int not nullable int so it can't be null ever?
You could change the definition of your CreatedBy as follows:
public int? CreatedBy { get; set; }
and they you can make the following check
if (e.CreatedBy == null) or if (e.CreatedBy.HasValue)
Ok, lot's of answers explaining the obvious. Here's a couple of ideas for actually solving your problem:
One alternative: Just use the default value 0.
Now, instead of checking for null in your original code, you can check if(CreatedBy > 0).
If you prefer to be more "explicit", you could use -1 to explicitly indicate "empty" or "not set", by setting it as a default value in the constructor. I'm not saying this is ideal in all situations, but it is fairly simple:
public YourClass(){
CreatedBy = -1;
}
public int CreatedBy { get; set; }
Obviously, this leads to the test: if(CreatedBy != -1).
Another alternative is to use nullable of int, as some have sugested, and check for null. This has the downside of having to deal with the type int? instead of the more "general" int everywhere you work with that value though. That may not be a problem, but sometimes it can get annoying, especially if you pass the value to other methods, classes, or whatever..
To answer your question, you can't check whether the value has been set, you can only check what value it has now. Any property will have a 'default' value when it's initialised. For most types (including Nullable), the default value is null, however for int the default value is 0.
If you're sure that nobody would ever set this property to 0 for any other reason, then you can test for:
if (e.CreatedBy == 0)
...however, if 0 is a valid value for this property under another circumstance, then testing for 0 won't help you. Equally, it you change the property to nullable, then you can test for:
if (e.CreatedBy == null)
...as per your original design, but if there is any other reason why the property might be set to null then again you're not finding out if it had ever been set, only that the last time it was set, it was set to null.
If you want to really know whether the value has been set, you need to arrange for something else to happen when the setter is used, for example to set another flag. Here's an example of doing exactly this, where the CreatedByHasBeenSet property is false (the default value of bool!) until the setter on CreatedBy is called:
private int createdBy;
public int CreatedBy
{
get
{
return this.createdBy;
}
set
{
this.createdBy = value;
this.CreatedByHasBeenSet = true;
}
}
public bool CreatedByHasBeenSet { get; private set; }
public bool PrepaymentCalculating { get; set; }
So I declare a variable on one of my classes like that. I want this to default to 'null' and not false. Would I just need to make this a nullable boolean? Or is there a better way to do this?
Would I just need to make this a nullable boolean?
Yes.
Or is there a better way to do this?
No.
You can achieve this with
public bool? PrepaymentCalculating { get; set; }
try
public bool? PrepaymentCalculating { get; set; }
Here's a post on Nullable Types
public bool? PrepaymentCalculating { get; set; }
will make it nullable. Read about it here
If you want it to be null then you need to make it a nullable type.
Like everyone else said, but I thought I'd add, what's your purpose here? It's not often that I want to expose a nullable bool, since this means that everything that uses this property must account for a possible null value.
But sometimes I want to know if it's been initialized or not in a given context, and if not, then use a value from somewhere else (e.g. to cascade property values). In this case you might want to use a pattern like this:
public bool PrepaymentCalculating {
get {
if (_PrepaymentCalculating != null ) {
return (bool)_PrepaymentCalculating;
} else {
return somethingElse; // bool
}
}
set {
_PrepaymentCalculating = value;
}
} protected bool? _PrepaymentCalculating =null;
bool can't be null. The default is probably false (but don't quote me on that).
If you want it to be null, then yes you have to declare it as nullable.