Should I make object properties nullable or use default CLR values ​​for each type?

I am trying to find a better way to handle default values. Setting the ID value to 0 makes sense, but if it is a monetary value or another value that was not originally set when you encounter it later in your code, it is impossible to determine whether it was set or set to 0. If the money value is set to zero, then you know that it has not been installed. In addition, when working with a database, you just need to know whether to write a null value in a field against trying to figure out whether it should be null or not.

What is an acceptable way to handle this?

Class MyModel { public int Id {get;set;} public string Title {get;set;} public DateTime CreatedDate {get;set;} public bool IsActive {get;set;} //CLR will automatically set these values Public MyModel() { Id = 0; Title = String.Empty; CreatedDate = "1/1/0001"; IsActive = false; } } 

against

 Class MyModel { public int? Id {get;set;} public string Title {get;set;} public DateTime? CreatedDate {get;set;} public bool? IsActive {get;set;} //CLR will automatically set these values Public MyModel() { Id = null; Title = null; CreatedDate = null; IsActive = null; } } 
+8
c # architecture
source share
5 answers

You can always mix approaches, depending on your domain.

 static class ID { public const int Unassigned = -1; } class MyModel { public int Id { get; private set; } public string Title { get; set; } public DateTime CreatedDate { get; set; } public bool IsActive { get; set; } public bool? IsAwesome { get; set; } Model () { // you may use "default" constants... Id = ID.Unassigned; } // you may use optional parameters or overloads public MyModel (string title, DateTime created = DateTime.Now, // default values may be concrete bool? isAwesome = null) // or nullable as well : this () // and you can chain-call constructors! { Title = title ?? "<no title>"; // you don't always want null to come through CreatedDate = created; IsAwesome = isAwesome; } } // Possible usages: var model = new MyModel ("Hello", new DateTime (2001, 1, 1)); var model = new MyModel ("world", isAwesome: true); var model = new MyModel (null) { IsActive = true }; 

For some attributes, it may make sense to have null values, as in "not set".

In your example, perhaps the model does not really have a Id before it is stored in the database. If this is the case, and without an id-less model makes sense from the point of view of business logic , a value with a zero value of Id better than Id = 0 . However, if your application never works with id-less models and usually expects Id be something equal, it would be crazy to write

 if (model.Id != null) 

every time you want to do something about it.

In this case, you should probably go with Id = 0 by default.
You can also introduce a constant (as I did above), although I would not recommend it for anything other than ids, and only if they are heavily used by code elsewhere.

Again, it all depends on the domain.
Your task is to prevent the creation of objects that violate business rules.

+3
source share

What is an acceptable way to handle this?

Received? It depends on the domain.

If the monetary value is set to null, then you know that it has not been set.

Not necessary. Imagine that I am using a banking application, and I want to find a specific transaction, and I get a dialog that looks like this:

 Enter the fields you know: Transaction date: 6/26/2011 Payee: Apple Amount: 

TransactionSearchParameters.Amount should now be set to null. You cannot distinguish this from the fact that it is not installed.

In addition, when working with a database, you just need to know whether to write a null value in a field and try to figure out whether it should be null or not.

You should spend more time correctly modeling your domain, and then let ORM figure out how to correctly get this material in the database.

+3
source share

Just the idea to add here, there is always a null object template for complex types when you need to use it.

+2
source share

It depends on how you are going to use your code. If the properties are simple types, such as integers and strings, the default values ​​are better if the properties are objects on their own, I used nulls, because in C # / Java / PHP object references are really pointers to objects and it’s better to use .

But if your properties are collections, such as lists or maps, its “best practice” to create a collection and leave it empty, not null.

Greetings.

0
source share

Well ... the "best" answer (very stubborn, but I mean) is when you do not need to distinguish between the two, because there is only one possible state: p>

 class MyModel { public int Id {get; private set;} public string Title {get; private set;} public DateTime CreatedDate {get; private set;} public bool IsActive {get; private set;} Public MyModel(int Id, string Title, DateTime CreatedDate, bool IsActive) { this.Id = Id; this.Title = Title; this.CreatedDate = CreatedDate; this.IsActive = IsActive; } } 

I know that this is not always possible, for example Query by Example.

The use of "magic numbers" such as "Setting the ID value to 0 makes sense ..." is usually avoided. Once you do this, each piece of code you write must be encoded to know what the magic number is and what they mean. This is rarely achieved and is full of nasty looking and error prone code.

If you just SHOULD have a distinction between a field that matters and not, your later example is a little better. At least here you value types are explicitly valid or invalid. However, using Nullable <T> means that you must use another tool to determine if a class, string, or other reference type is invalid.

IMO, you are better off with the following, although this is becoming very verbose, as you will see.

 class MyModel { private int _id; public bool HasId { get; set; } public int Id { get { if (!HasId) throw new System.InvalidOperationException(); return _id; } set { HasId = true; _id = value; } } private string _title; public bool HasTitle { get; set; } public string Title { get { if (!HasTitle) throw new System.InvalidOperationException(); return _title; } set { if (value == null) throw new System.ArgumentNullException("Title"); HasTitle = true; _title = value; } } private DateTime _createdDate; public bool HasCreatedDate { get; set; } public DateTime CreatedDate { get { if (!HasCreatedDate) throw new System.InvalidOperationException(); return _createdDate; } set { HasCreatedDate = true; _createdDate = value; } } private bool _isActive; public bool HasIsActive { get; set; } public bool IsActive { get { if (!HasIsActive) throw new System.InvalidOperationException(); return _isActive; } set { HasIsActive = true; _isActive = value; } } } 

Finally, if you go this route, the code generator will serve you well.

0
source share

All Articles