I have a class containing a number of properties, something like:
public class Update
{
public int Quantity { get; set; }
public decimal Price { get; set; }
public string Name { get; set; }
}
Each instance of Update does not necessarily have each property set, and another part of the system needs to know which have been set, and which haven't.
One option I've got is to make all the value types Nullable and so a null value would represent the concept of not being set. Whilst this would work, I don't really like the idea of having some properties explicitly Nullable (the value types) and some nullable by virtue of being a reference type. The class definition would look ugly and I'm not convinced a null check is semantically the best approach.
I could create a class very similar to Nullable<T> that has no constraint on the T with an IsSet property. I prefer this option to using Nullable, but I'd still like to see if anyone has an alternative representation that's better than the options I've suggested.
You really should stick to the preexisting idiom here. Use the built-in nullability.
I see your concern with nullability being different for value and ref types. Your workaround would work. But it is just a cosmetic change which gains you litte. I recommend that you change yourself instead of changing the code in this case. Try to fit yourself to the existing conventions.
Edit: Sometimes you need to be able to make a value optional in generic code. In this case you need to use some custom option type. By from experience I can tell that this is pretty nasty to use. It is not my solution of choice.
The reference types are already nullable, effectively - if you use int?, decimal? and string then every one of your properties can be null.
The problem comes if you ever want to set the string value to a null reference - if null is effectively a valid value which is set.
You certainly could write a Maybe<T> type, but I'm not sure I would - I would probably just use null... aside from anything else, it'll be more familiar for others reading the code who are used to C# idioms. For all the "anti-null" sentiment around (which I do share in many situations) there are cases where it's the simplest approach.
I don't really like the idea of having some properties Nullable (the
value types) and some not (the reference types)
Reference types are obviously nullable.
string t = null; //is totally valid
I'd say that Nullable is exactly what you want to use for this purpose.
You could wrap the members with properties (as you already do) to have the class show normal values to the outside alongside with "is it set"-methods to check if needed. But on the inside I'd use Nullable.
To suggest you something new... If you just talking about one class like Update with a limited number of members I would use just IsSet.
But if you have i.e. a number of similar classes with this behavior or a lot of properties I could suggest you using t4 templates. You can, in example, get class properties (of needed type or attribute) as it described in this article and auto generate code based on the list of properties (implementing any design you want automatically)
I could describe it more if one is interested...
The solution here to
use nullable wherever null is not a valid option
use a default value wherever null is a valid option but you are perfectly sure that a given value won't occur
use a boolean flag for each property where null is a valid value and you can't name a default which won't be used ever.
Examples:
Quantity should be nullable, because if it is set its value won't be null ever
Name should be defaulted to "" if Name might be null (the lack of a name) and you are sure Name will never be ""
A flag, let's say nameSet should be used if Name might have a null value and you can't think of a default value. This flag would be false by default and when you first set the value of Name, the flag should be set to true too.
If you want to handle all your properties in the same way a solution would be to create a class which would contain an Object and a boolean flag. The Object would store the value of the property and the flag would store whether the property was initialized, but I don't like this, because it creates a boolean flag even if it's not needed.
Related
I've recently seen the following code:
public class Person
{
//line 1
public string FirstName { get; }
//line 2
public string LastName { get; } = null!;
//assign null is possible
public string? MiddleName { get; } = null;
public Person(string firstName, string lastName, string middleName)
{
FirstName = firstName;
LastName = lastName;
MiddleName = middleName;
}
public Person(string firstName, string lastName)
{
FirstName = firstName;
LastName = lastName;
MiddleName = null;
}
}
Basically, I try to dig into new c# 8 features. One of them is NullableReferenceTypes.
Actually, there're a lot of articles and information about it already. E.g. this article is quite good.
But I didn't find any information about this new statement null!
Can someone provide me an explanation for it?
Why do I need to use this?
And what is the difference between line1 and line2?
TL;DR
The key to understanding what null! means is understanding the ! operator. You may have used it before as the "not" operator. However, since C# 8.0 and its new "nullable-reference-types" feature, the operator got a second meaning. It can be used on a type to control Nullability, it is then called the "Null Forgiving Operator".
Basically, null! applies the ! operator to the value null. This overrides the nullability of the value null to non-nullable, telling the compiler that null is a "non-null" type.
Typical usage
Assuming this definition:
class Person
{
// Not every person has a middle name. We express "no middle name" as "null"
public string? MiddleName;
}
The usage would be:
void LogPerson(Person person)
{
Console.WriteLine(person.MiddleName.Length); // WARNING: may be null
Console.WriteLine(person.MiddleName!.Length); // No warning
}
This operator basically turns off the compiler null checks for this usage.
Technical Explanation
The groundwork that you will need to understand what null! means.
Null Safety
C# 8.0 tries to help you manage your null-values. Instead of allowing you to assign null to everything by default, they have flipped things around and now require you to explicitly mark everything you want to be able to hold a null value.
This is a super useful feature, it allows you to avoid NullReferenceExceptions by forcing you to make a decision and enforcing it.
How it works
There are 2 states a variable can be in - when talking about null-safety.
Nullable - Can be null.
Non-Nullable - Can not be null.
Since C# 8.0 all reference types are non-nullable by default.
Value types have been non-nullable since C# 2.0!
The "nullability" can be modified by 2 new (type-level) operators:
! = from Nullable to Non-Nullable
? = from Non-Nullable to Nullable
These operators are counterparts to one another.
The Compiler uses the information, you define with those operators, to ensure null-safety.
Examples
? Operator usage.
This operator tells the compiler that a variable can hold a null value. It is used when defining variables.
Nullable string? x;
x is a reference type - So by default non-nullable.
We apply the ? operator - which makes it nullable.
x = null Works fine.
Non-Nullable string y;
y is a reference type - So by default non-nullable.
y = null Generates a warning since you assign a null value to something that is not supposed to be null.
Nice to know: Using object? is basically just syntactic sugar for System.Nullable<object>
! Operator usage.
This operator tells the compiler that something that could be null, is safe to be accessed. You express the intent to "not care" about null safety in this instance. It is used when accessing variables.
string x;
string? y;
x = y
Illegal! Warning: "y" may be null
The left side of the assignment is non-nullable but the right side is nullable.
So it does not work, since it is semantically incorrect
x = y!
Legal!
y is a reference type with the ? type modifier applied so it is nullable if not proven otherwise.
We apply ! to y which overrides its nullability settings to make it non-nullable
The right and left side of the assignment are non-nullable. Which is semantically correct.
WARNING The ! operator only turns off the compiler-checks at a type-system level - At runtime, the value may still be null.
Use carefully!
You should try to avoid using the Null-Forgiving-Operator, usage may be the symptom of a design flaw in your system since it negates the effects of null-safety you get guaranteed by the compiler.
Reasoning
Using the ! operator will create very hard to find bugs. If you have a property that is marked non-nullable, you will assume you can use it safely. But at runtime, you suddenly run into a NullReferenceException and scratch your head. Since a value actually became null after bypassing the compiler-checks with !.
Why does this operator exist then?
There are valid use-cases (outlined in detail below) where usage is appropriate. However, in 99% of the cases, you are better off with an alternative solution. Please do not slap dozens of !'s in your code, just to silence the warnings.
In some (edge) cases, the compiler is not able to detect that a nullable value is actually non-nullable.
Easier legacy code-base migration.
In some cases, you just don't care if something becomes null.
When working with Unit-tests you may want to check the behavior of code when a null comes through.
Ok!? But what does null! mean?
It tells the compiler that null is not a nullable value. Sounds weird, doesn't it?
It is the same as y! from the example above. It only looks weird since you apply the operator to the null literal. But the concept is the same. In this case, the null literal is the same as any other expression/type/value/variable.
The null literal type is the only type that is nullable by default! But as we learned, the nullability of any type can be overridden with ! to non-nullable.
The type system does not care about the actual/runtime value of a variable. Only its compile-time type and in your example the variable you want to assign to LastName (null!) is non-nullable, which is valid as far as the type-system is concerned.
Consider this (invalid) piece of code.
object? null;
LastName = null!;
When the "nullable reference types" feature is turned on, the compiler tracks which values in your code it thinks may be null or not. There are times where the compiler could have insufficient knowledge.
For example, you may be using a delayed initialization pattern, where the constructor doesn't initialize all the fields with actual (non-null) values, but you always call an initialization method which guarantees the fields are non-null. In such case, you face a trade-off:
if you mark the field as nullable, the compiler is happy, but you have to un-necessarily check for null when you use the field,
if you leave the field as non-nullable, the compiler will complain that it is not initialized by the constructors (you can suppress that with null!), then the field can be used without null check.
Note that by using the ! suppression operator, you are taking on some risk. Imagine that you are not actually initializing all the fields as consistently as you thought. Then the use of null! to initialize a field covers up the fact that a null is slipping in. Some unsuspecting code can receive a null and therefore fail.
More generally, you may have some domain knowledge: "if I checked a certain method, then I know that some value isn't null":
if (CheckEverythingIsReady())
{
// you know that `field` is non-null, but the compiler doesn't. The suppression can help
UseNonNullValueFromField(this.field!);
}
Again, you must be confident of your code's invariant to do this ("I know better").
null! is used to assign null to non-nullable variables, which is a way of promising that the variable won't be null when it is actually used.
I'd use null! in a Visual Studio extension, where properties are initialized by MEF via reflection:
[Import] // Set by MEF
VSImports vs = null!;
[Import] // Set by MEF
IClassificationTypeRegistryService classificationRegistry = null!;
(I hate how variables magically get values in this system, but it is what it is.)
I also use it in unit tests to mark variables initialized by a setup method:
public class MyUnitTests
{
IDatabaseRepository _repo = null!;
[OneTimeSetUp]
public void PrepareTestDatabase()
{
...
_repo = ...
...
}
}
If you don't use null! in such cases, you'll have to use an exclamation mark every single time you read the variable, which would be a hassle without benefit.
Note: cases where null! is a good idea are fairly rare. I treat it as somewhat of a last resort.
I don't believe this question can be discussed without specific C# version being used.
public string RpyDescription { get; set; } = null!;
This is common in .NET 6 Core ... in fact it's required if you want to describe a string as not being nullable. One reason this exists is when one is working with SQL databases where a field can be set to "Allow Null". Even more so when working with JSON structures that accept null. EF needs to know.
Reference Type (Heap - pointer to memory location where the data is stored) of Value Type (Stack - memory location where data is stored).
.NET 6 (C#10) enables nullable context for the project templates by default (prior to this nullable context is disabled by default).
In EF/Core, it's very important to understand relationship between database null and model/entities null.
This question needs to be updated, in C# 10 in object relational mapping, this operator, combined with the ? operator is critical, this is a way to tell other coders on the project, future coders, and remind yourself how the data is going to end up being consumed and the null rules regarding that data.
public string Data { get; set; } = null!;
public string? Nullable { get; set; }
The beauty of this is that you don't have to go and look at the API docs(which you might not have), or go look through your database (which you might not even have access to). You already know by glancing at the class what the rules regarding null values are.
The downside is that if you instantiate the class, and don't have the information you need to instantiate the NOT NULL values, you will get strange default values that don't always make sense. First of all this doesn't happen nearly as commonly as people think and often comes from lazy programming. When you instantiate an instance of a class. You should calculating or assigning those NOT NULL properties. Right away. If you declare a car, and in your database or API cars have wheels, if you declare a car without assigning property values to the wheel.
Then did you truly instantiate the car in a meaningful way? You certainly didn't define the car the way the Database understands a car, it's a car with no wheels and it shouldn't be, doing this might be convenient but it goes against basic principles of object oriented programming.
are there exceptions for example perhaps the value can't be known at that point in time or until other events have transpired in these edge cases. Create a meaningful default value manually, if your default value hits the database you will know EXACTLY what's wrong
for people discussing unit tests why would you test the null case when the null case is impossible in the context of the object there is no need to have an understanding of how a car without wheels would behave for example. This is a silly, badly designed test.
I would go so far as to say that when it comes to strings this operator should be used the overwhelming majority of the time. When we declare int, or bool, or float, we have the understanding that these cannot be null unless we say so explicitly. Why in the world would you advocate for a different rule for strings!? the fact that we couldn't do this with strings previously was a design flaw.
I'm trying to detect whether a type can be nullable or not at runtime to convert that type to the corresponding GraphQL type so that, for example:
With nullable reference types enabled:
string is converted to String!
string? is converted to String
With nullable reference types disabled:
string is converted to String
NonNull<string> is converted to String! (NonNull is a custom library type)
I'm having trouble adapting the code that detected the nullability of a type:
bool isNullable = !typeInfo.IsValueType;
How can I change it so that it works with nullable reference types both enabled and disabled?
Note that there are good ways to check for "the old" nullable types that applies to value types that is documented thoroughly here on Stack Overflow.
I will then instead only focus on nullable reference types, and provide the means to check if one of those are in effect.
Let me sum up my comments on the question first as they are rather important.
Contrary to the name of the new feature, nullable reference types is not about the types, but rather about the things these types are used for. These things are:
Fields
Properties
Method return values
Method parameters
Now, of course this also applies to local variables but you need a whole 'nother kind of introspection to deal with decoding instructions. I do not know how, or even if, this kind of information is encoded in the actual instructions for local variables.
OK, so with that out of the way, let's look at some code (btw, I'm using LINQPad with Roslyn experimental mode to test all this):
public string? Nullable;
public string NonNullable;
These are two public fields. Ignore whether this is a good idea or not. How would you check the type of these fields and detect the presence or lack of this question mark?
Well, let's try the simple route:
Type nullable = GetType().GetField("Nullable").FieldType;
Type nonNullable = GetType().GetField("NonNullable").FieldType;
Console.WriteLine(ReferenceEquals(nullable, nonNullable));
Running this gives me:
True
So clearly this doesn't work. The Type objects are the exact same instance. They don't just compare equal, I got the same thing back, no difference. Basically, FieldType is oblivious to the presence or lack of this question mark.
My comments up above has some of those details but the main reason for this is at all existing nuget packages and compiled code will still work with this new support because of this. There is no need for any code to be rewritten to handle something like NullableReferenceType<T> suddenly. This is a good thing, but also means that you will still be passing null-references around and getting them back from existing nuget packages.
OK, so then, how would we detect this? The answer is that the information about the nullability is not attached to the type, as I mentioned above, but rather to the thing that has the type, in this case the fields.
Let's show attributes on these fields (again I'm using LINQPad):
GetType().GetField("Nullable").GetCustomAttributes().Dump();
GetType().GetField("NonNullable").GetCustomAttributes().Dump();
This gives this output:
As you can see here, the Nullable field has an additional attribute, NullableAttribute. I must confess that I do not know what that other attribute is about, I will have to investigate more.
This NullableAttribute attribute is much more complex than this simple example shows, as it has a collection property with bool values. Let's look at a slightly more complex example:
public List<string>? Nullable1;
public List<string?>? Nullable2;
Here, both fields are nullable references to a list, the difference is that I've said that one of the lists contains nullable references to strings, the other doesn't.
Here's some reflection to look at these collections:
GetType().GetField("Nullable1").GetCustomAttributesData().Dump();
GetType().GetField("Nullable2").GetCustomAttributesData().Dump();
and their output:
Here you can see that there is a difference on the second element in this collection (I've "circled" them with red ... rectangles ...), I expect the first element applies to the list, the second one to the first generic type parameter. If you have generic lists containing generic types, the number of parameters will increase accordingly.
You can also find more information on this excellent blog post by Rico Suter.
In my use case I need a required boolean property, for example:
public class Todo
{
[Required]
public bool IsDone {get; set; }
}
I experienced a bug in my Entity Framework project due to a missing property mapping (value was not set) of a boolean property. As a result I always stored the default boolean value ‘false’ while it’s actually not filled in. When not filled in I expect to throw a validation exception but because it’s a primitive type the validation attribute makes no sense as it always have a default value which is sufficient to pass. I don’t want to have a default value and the validation attribute should throw an exception when the value is not set.
A solution what I came up with is to use nullable booleans with the required attribute. In case the property is not set the required attribute will throw an exception which is great. On the other side it's pretty weird to have a required nullable boolean because you known it's always filled in (due to the required attribute) and it makes the business logic about this property less readable (IsDone.HasValue? IsDone.Value : false; /Should not be possible because it's required/).
Any other solutions possible?
There are a number of options here.
What you want is a triple state mechanism : not set, true, false
Nullable bool does provide that, however the main question is if this is clear to consumers.
A second option would be to create a triple state enum and use that instead.
Is it clearer? Maybe
Is it extensible? Yes, but do we really require more then 3 states?
Between the two, I would go with a nullable bool myself. In the end it's a pick your poison kind of situation.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between Property and Field in C#
I know it is a very basic question but I cannot read any valid answer after searching
E.g
public string abc;
public string abc { get; set; }
Please describe this.
(About my terminology: "field" = public variable, "property" = get/set)
One thing to be mentioned additionally to the differences in usage: A property, unlike a field, gets compiled to a method (I think it's called something like get_abc internally). Declaring an auto property from beginning on has therefor two advantages:
1) No problems with reflection. If some reflection code is based on the value being a field, and later you think "well, now I'd like to add null testing" and change to a property, then the reflection code will eventally fail (unless you expected that in the reflection, but that would be extra effort for nothing imho)
2) "Warning" of possible side effects. Fields can only change their values, methods can do arbitrary things to a class. So, declaring a property from beginning on signalizes the possibility of other changes happening in the background. (Of course one shouldn't do weird stuff in a setter, but sometimes it isn't impractical to get additional initialization from one value provided; e.g. measuring the length of a list)
I also would say that it's good style to use properties wherever possible. Especially for the two reasons provided, but also for consistency.
Variables store direct value but property are a window to your class and its variables.
Even though they work the same(almost), one very good thing with field is that if you want to do some extra work with field (like validation or doing any calculations) you can do so.
This will explain you
public string _abc;
public string abc
{
get
{
return _abc;
};
set
{
if (value == null)
_abc = "";
else
_abc = value;
};
}
Here if null is passed to property abc then it will be checked it and an empty value will be assigned to _abc. otherwise value.
If we wanted this with a variable. every where we had to do this.
if(foo == null) // here foo is some string
_abc = ""
else
_abc = foo;
with property this can be done like
abc = foo;
Now it will check for in the set section of property.
Properties can contain some code on setting/getting the value. Public variables can't and will not contain any code when you access them. This is a huge difference.
Using a property you're saying to whomever uses you're code that there might be some code behind the value now or in the future.
Using a public variable you're saying its just a boring old field that will contain some value.
One reason for using an auto property instead of a Field is compatibility.
For example, when you assign a field, the CLR does just that. It sets the field.
When you have a property (auto or not), and you type
someObject.Whatever = "Value";
it looks like you are assigning a field, but in reality, the C# compiler inserts something like this for you:
someObject.set_Whatever("Value");
That's not the same as setting a field. And if you have a field and change it to a property later (e.g. if you want to implement change notifications or things like that), you will have to recompile all assemblies that used the original field, since assigning a Field requires different code than setting a property (no matter if auto or not).
There is almost never a reason to use a public field. Automatic properties can be inlined at runtime, so there would be no performance difference. And they leave the possibility open to add additional logic to your get / set methods without having to recompile dependent assemblies.
Same difference as a property over public variable such as property support binding but variable not.
Is it ok to construct my object entities with this type?
public class Patient
{
public Datetime? AdmissionDate { get; set; }
public double? AdmissionFee { get; set }
public int? RoomNumber { get; set }
}
WHat is the drawback if I implemented this in all my entities, because recently, I always encounter situation where I really need to set the value to null, specially in DateTime. My current solution was put DateTime.MinValue when fetching null datetimes record from the database, and when Im displaying the result to Ui, I just check it like this.
if (patient.AdmissionDate == Datetime.MinValue)
{
DisplayAdmissionDate(string.empty)
}
else
{
DisplayAdmissionDate(patient.AdmissionDate)
}
Yes, in gridview, I have to put it on the Databound event, so when i have million data to display, I thought checking each of the datetime's each loop was not the most elegant way so, to this problem, I find this ? type where I can put null values, and I'm planning to ?ed all my properties, so in the future, putting null values to this value types will not be a problem. Any advise guys? TIA
This is one of those situations where no single, dogmatic answer covers all cases.
You can’t get away with always using nullable types (or always avoiding them). You should think about each case and use the one that you actually need.
You mentioned that you often needed a nullable DateTime. So why can’t you just use a DateTime? in those cases? This should be an independent consideration from all other fields, especially ints.
The null value in nullable types is intended to mean the value is something like unspecified, unavailable or unknown. There are many situations where this concept exists (e.g. users on a website may or may not specify their date of birth, so that should be a DateTime?), but there are also many situations where this concept makes no sense (e.g. the number of items in a List — if the List itself isn’t null, then clearly it has a definite number of items, so that should be int, not int?).
The object always should contain at least one non-nullable ValueType as a Primary Key. In your case, you should use
public int ID {get;set;}
Doing this, you can always identify an object. The rest of the properties can be nullable.
The check for nullable is perfectly fine, unless the GridView can detect that on its own already. Nullable types were introduces exactly for that purpose, allowing a ValueType to have null as a value. The performance aspect should be minimal isn't complex in any way and optimizing it would be a case of premature optimization.
If you want to know more about the implementation of Nullable<T>, have a look here (sadly, the original page currently is down, so the webcache version has to be sufficient. The code is readable though, just the blogpost is abit broken).
The downside with nullable types is that you must always check to see wether they have a value or not before operating on them...
if(AdmissionFee.HasValue) total += AdmissionFee;
instead of just
total += AdmissionFee;
You may get problems with data binding, I don’t think WinForms will cope well as it predates nullable types.
If an item can be null in real life then a nullable type is a good solution as it makes the clear. However don’t just use them for the sake of it.
According to https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/property?redirectedfrom=MSDN:
AVOID throwing exceptions from property getters.
Since SomeNullableProperty.Value can throw a NullReferenceException, I'd say you should at least have logic in your getter to make sure there's a default value.