Initialize a completely empty ViewModel? - c#

I am trying to initialize an own view model in which every property is set as null or "" but when I use
ViewModel model = new ViewModel
any property that is of type int gets set with 0 as it's value. I know I could go in and manually set each property to null or "" but that can get lengthy, what is the proper way to initialize a completely empty view model?

A property of type int cannot be null or ""
If you want to do that you should create a Nullable<int> (for null):
class ViewModel
{
public int? SomeInt{get; set;}
}
Setting an int to "" makes completely no sense

No matter which class you are using (Model or ViewModel), only set nullable fields by ? suffix after type like int. Note that System.String is a reference type and already nullable. Nullable<T> and the ? suffix are for value types such as Int32, double, DateTime, etc.
public int? name {get; set;}//as nullable field
And
public int name {get; set;}//as not nullable field

Related

New c# nullable option

In new version of C# is default option nullable. I mean this
It's really good feature for me. But I don't understand one thing. Is property nullable by me or by program?
I know that this property should never be null because I fill it in the form and never set it as null. But in general it can be null. How should I mark it?
Example:
UserModel:
public string? Name { get; set; }
public string Name { get; set; } = null!
I'm really confused.
I know that this property should never be null because I fill it in
the form and never set it as null. But in general it can be null. How
should I mark it?
If it is set to non-null in the constructor, then you can declare it a string rather than string? because it really is guaranteed to never be null.
If, however, it is null after the constructor has run (and before any other methods are called) then it CAN be null and you should declare it as string?.
The dichotomy you face is that (from what you say) it should never be null when the class is used correctly - i.e. if the calling code does indeed call the method that initialises the property to non-null before accessing it, it will be guaranteed to be not null - which means you would like to declare it as a non-null string so that callers don't need to use the null-forgiving ! operator to suppress nullable warnings.
What to do in this case? Well I think you have three possibilities:
Declare the property as nullable: string? and let the callers suppress the nullable warning or check the value for null.
Initialise the property to a non-null default such as string.Empty and declare the property as non nullable string.
Assume that accessing the property when it is null is a programming error, and throw an appropriate exception.
For the last case, you could do something like this:
private string? _name;
public string Name
{
get
{
if (_name == null)
throw new InvalidOperationException("Do not access Name without setting it to non-null or calling Init()");
return _name;
}
set
{
if (value == null)
throw new ArgumentNullException("value", "You cannot set Name to null.");
_name = value;
}
}
This assumes that there's a method called Init() that can be called to initialise Name, but of course your code may vary.
Regardless of which of those approaches you take, you should really check for null in the property setter, as shown above.
Note that a more succinct way of writing the setter null check is:
set
{
_name = value ?? throw new ArgumentNullException("value", "You cannot set Name to null.");
}
Where a value can be null, and the <Nullable>enable</Nullable> value is set in your *.csproj file, you must declare those values as nullable.
In your given example, the nullable type (instead of assigning null as a default) is the way to go:
public string? Name {get; set;}
You'll also notice VS complaining at you with warnings every time you introduce a property etc which can be nullable, but isn't marked as such.

Non-nullable property is null

I have a very simple class Address:
public class Address
{
public string Name { get; set; }
public string Country { get; set; }
}
I declared Name as string and NOT as string?, because it should never be null.
Now i have a method where i get an instance of this class as parameter:
public List<Address> SearchAddress(Address search)
{
...
if (!search.Name.Equals(string.Empty))
{
temp = query.Where(a => a.Name.Contains(search.Name));
}
...
}
Now my colleague called this method and i got a System.ArgumentNullException because search.Name is null.
If i have a non-nullable int property i get 0 as value if i don't assign anythig to it.
Why is a non-nullable string property null if no value is assigned and not just string.Empty?
int is a non-nullable value type (i.e., a struct). Value type fields will be initialized to their default value. E.g., int to 0, bool to false, etc. Full list here.
When you want to be able to assign null to value type variables, you can use Nullable<T> where T : struct or, in the case of an int, Nullable<int>/int?.
string, on the other hand, is a reference type. Reference types can be null, and reference type fields will be initialized as null. As such, having a Nullable<string>/string? is not allowed nor would it make sense.
In your case, you'll want to check whether the Name string is null or empty
if (! String.IsNullOrEmpty(search.Name)) { ... }
String can hold null values, its simple as that!
String is a reference type, but is has certain behavior of value type.
Please read this topic : Null strings and empty strings
You can use the string.IsNullOrEmpty to determine a instance if it is Null and empty string .
string is a reference type and it's null by default. String.empty is equivalent to a double quoted empty string ("") and hence null is not the same as String.empty.

What does it mean when it says 'int' is never equal to 'null' of type 'int?' [duplicate]

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; }

Deserialization behaviour

I have serializable class
[Serializable]
public class Entity
{
public Guid? SomeId {get;set;}
...
}
In DB it has SomeId == null
When restored from DB it has SomeId == Guid.Empty, but if I add emty default constructor it is restored with SomeId == null.
Can anyone explain such behaviour.
Thanks
The empty constructor is required by the serializer to create an instance of the Entity. After creating this instance, it will perform its deserialization: setting the individual properties with their serialized values. That is why the property setter must also be public.
To find out your actual problem you can start to verify whether the data has been properly serialized.
I assume you are using OR mapper software.
In that case it could also be that the OR mapper is initializing the SomeId property with a default value.
Because you use Nullable types Guid?, you add emty default construtor so that SomeId is null.
eg: if you use public bool? IsTrue { get; set; },the IsTrue property can be assigned the values true or false, or null. details Nullable types in msdn: http://msdn.microsoft.com/en-us/library/1t3y8s4s(v=vs.80).aspx

Nullable string property/column in nHibernate + Fluent

I'm new to nHibernate universe, so this question can be idiot ..
I have a table with a nullable nvarchar column.
In the mapping i use this Map(c => c.Genero, "genero").Nullable();
In the property i use trim to set the value, so i have a private string and a public virtual string.
When i do an select in this table i receive an runtime error in the setter of this property.
I tryed to pass this property to Nullable, but i receive a compile-time error saying The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable<T>'.
How can i do this ?
Thanks for everyone !
UPDATE
If i use just the property with { get; set; } works normally, but i need to trim.
The problem may be that you can't trim a null string. Try:
public string Genero
{
get { return _genero; }
set { _genero = string.IsNullOrEmpty(value) ? value : value.Trim(); }
}
Depending on your mapping, this may cause the trimmed string to be written to the database when the session is flushed. It might be better to map the string as a private field and trim it in the getter.

Categories