what does question mark means in MVC? - c#

what does "?" mean in MVC , when we write it with data type for example
public Grade? Grade { get; set; }
what does "?" shows? and what will be difference if i will not write "?" ?

If you want to make any property nullable then we add question marks "?"
public Grade? Grade { get; set; } --> Grade property will accept null value also.
public Grade Grade { get; set; } --> no null value allowed for this property

Grade? is the same as Nullable<Grade>. It's a C# language feature, not specific to MVC.

? represents a nullable type. Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type, because reference types already support null.
From the link you provided for your tutorial:
The Grade property is an enum. The question mark after the Grade type
declaration indicates that the Grade property is nullable. A grade
that's null is different from a zero grade — null means a grade isn't
known or hasn't been assigned yet
So, in the same example Enrollment is a reference type which, is nullable by default. So won't need explicit ? when declaring objects of that class.
This is a valid nullable declaration. You can assign null to it:
int? num = null;
You can also do a:
int y = num.GetValueOrDefault();
Where y will get whatever value num contains (if it contains a value), otherwise null which is default for nullable types.
You can expicitly check if it contains null by:
num.HasValue();
You get values out of nullable typed variables like this:
int y = num.value;

In the link you provided in the comments, Grade represents an enum which is a value type. Value types don't have the ability to point to null, so it needs to be suffixed with the ? symbol to represent a null value. It's essentially the same as saying:
public Nullable<Grade> Grade { get; set; }
More examples:
int a = null; //not allowed
int b? = null; //allowed
string refType = null; //allowed
int x? = 2;
int y? = 2;
Keep in mind that if you try to perform an operation on nullable types, the operators will be lifted:
book areEqual = x == y;
which translates to:
bool areEqual = (x.HasValue && y.HasValue) ? (x.Value == y.Value) : false;
That means that the nullable type can use the operators from the original value type.

The id may be null while passing as a parameter to action method.

Related

How to make Object property of a C# class optional?

I am trying to make a model class in C# in which i require object/List properties as optional property:
public class Customer
{
[JsonProperty("Custid")]
public string CustId { get; set; }
[JsonProperty("CustName")]
public string CustName { get; set; }
}
public class Store
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("Name")]
public string? Name { get; set; }
[JsonProperty("Customer")]
public List<Customer>? Customers{ get; set; } *//Error 1*
[JsonProperty("OtherProperty")]
public object? OtherProperty{ get; set; } *//Error 2*
}
The above code is giving error as :-
Error 1: The type 'object' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'
Error 2: The type 'List' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'Nullable'
Please Explain me the above scenario and provide me with the alternate solution.
string, List and object are all reference types. Those are nullable by default. The Nullable type (e.g. int? is a shorthand for Nullable<int>) is only used for value types.
In C# 8.0, a new feature was introduced that allows for non-nullable reference types - i.e. reference types that explicitly disallow null assignment. This is an opt-in feature - you can enable it to allow you to more clearly show intent about the references. If you use this, the syntax used to define nullable reference types is the same as for nullable value types:
string nonNullableString = null; // Error
string? nullableString = null; // Ok
Keep in mind that enabling non-nullable reference types means that all of the reference types that aren't followed by ? will be non-nullable; this might require you to make lots of changes in your application.
So there's your two choices. Either enable non-nullable reference types, and then you need to explicitly mark types that you want to have nullable, or stick with nullable reference types, and just use string instead of string? for the same result. I would encourage the use of non-nullable types by default, since it holds some promise for avoiding an entire class of very common programming mistakes.
If you aren't using C# 8:
object? doesn't exists. object is already nullable.
List<Customer>? doesn't exists. List<Customer> is already nullable.
If you want to use nullable reference types you must update your compiler version!
The Nullable<T> type requires that T is a non-nullable value type, for example int or DateTime. Reference types like string or List can already be null. There would be no point in allowing things like Nullable<List<T>> so it is disallowed.

String is Nullable returns false

Why does:
string s = "";
bool sCanBeNull = (s is Nullable);
s = null;
sCanBeNull equate to false?
I'm writing a code generator and need to ensure every type passed to it is nullable, if it isn't already.
//Get the underlying type:
var type = field.FieldValueType;
//Now make sure type is nullable:
if (type.IsValueType)
{
var nullableType = typeof (Nullable<>).MakeGenericType(type);
return nullableType.FullName;
}
else
{
return type.FullName;
}
Do I need to have to explicitly check for a string or am I missing something?
is tells you whether a value is of a particular type, or one derived from that particular type.
Nullable is a generic struct that allows for nullable versions of non-nullable values.
string is not a Nullable
To tell if a type can have null values use the fact that for all such types the default value is null, while for all other types it is not:
default(string) == null; // true
string is a reference type so it is not Nullable as that is reserved for value types.
In fact:
var nullable = new Nullable<string>();
Gives a compile time error.
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'
The rational behind System.Nullable is to be able to represent undefined Value Types using the null keyword. It does not mean that you can check whether some variable can be set to null using someVar is Nullable.
If at compile-time you cannot know beforehand whether some variable would be a value-type or a reference-type, you can use:
!someVar.GetType().IsValueType
But usually a generic argument would be a better approach.
Nullable is just a normal class like MyClass or System.String (Nullable<T> is struct though).
So if you type:
class _Nullable {}
struct _Nullable<T> {}
class Program
{
static void Main()
{
string a = "";
Console.Write(a is _Nullable);
}
}
You wouldn't be surprised if it returns false right ?
If you want to check if something is nullable or not you can use if(!(a is ValueType))
string a = "";
Console.Write("a is nullable = {0}", !(a is ValueType));
Output : a is nullable = true

Type checking on Nullable<int>

If have the following method:
static void DoSomethingWithTwoNullables(Nullable<int> a, Nullable<int> b)
{
Console.WriteLine("Param a is Nullable<int>: " + (a is Nullable<int>));
Console.WriteLine("Param a is int : " + (a is int));
Console.WriteLine("Param b is Nullable<int>: " + (b is Nullable<int>));
Console.WriteLine("Param b is int : " + (b is int));
}
When i call this method with null as a parameter, the type check returns false for this parameter. For example this code
DoSomethingWithTwoNullables(5, new Nullable<int>());
results in this output:
Param a is Nullable<int>: True
Param a is int : True
Param b is Nullable<int>: False
Param b is int : False
Is there any way to preserve the type information when using a Nullable and passing null? I know that checking the type in this example is useless, but it illustrates the problem. In my project, I pass the parameters to another method that takes a params object[] array and tries to identify the type of the objects. This method needs to do different things for Nullable<int> and Nullable<long>.
Going straight to the underlying problem, no, you can't do this. A null Nullable<int> has exactly the same boxed representation as a null Nullable<long>, or indeed a 'normal' null. There is no way to tell what 'type' of null it is, since its underlying representation is simply all-zeros. See Boxing Nullable Types for more details.
conceptually, new Nullable<int> is null.
If we generalise, forgetting about Nullable<T>:
string s = null;
bool b = s is string;
we get false. false is the expected value for a type-check on a null value.
You can try using Reflection to achieve this. Relevant article here.
Unfortunately, null does not point to any specific memory location, and thus there is no metadata that you can associate with it to lookup the type. Thus, you cannot gain any additional information about the variable.
Unless I'm misunderstanding the question, you can get the type using GetType(). For example,
int? myNullableInt = null;
Console.WriteLine(myNullableInt.GetValueOrDefault().GetType());
If myNullableInt is null, a default value will be returned. Check the type of this returned value and, in this case, it will return System.Int32. You can do an If..else/Switch check on the returned type to perform the relevant action.
(int? is the same as Nullable<int>)
You can't do this, nor should you want to. Since Nullable<T> is a struct, value-type variables of this type have all the type information you need at compile time. Just use the typeof operator.
On the other hand, you might have a Nullable instance whose type you don't know at compile time. That would have to be a variable whose static type is object or some other reference type. Howver, because a Nullable<T> value boxes to a boxed T value, there's no such thing as a boxed Nullable<T>. That instance whose type your checking will just be a T.
This is why you get the same result for is int and is Nullable<int>. There's no way to distinguish between a boxed int and a boxed int?, because there is no boxed int?.
See Nulls not missing anymore for details.
As it has already been pointed out null has no type. To figure out if something is int? vs long? you need to use reflection to get information about something storing the type. Here is some code that you may be able to use as inspiration (not knowing exactly what you try to achieve the code is a bit weird):
class Pair<T> where T : struct {
public Pair(T? a, T? b) {
A = a;
B = b;
}
public T? A { get; private set; }
public T? B { get; private set; }
}
void DoSomething<T>(Pair<T> pair) where T : struct {
DoMore(pair);
}
void DoMore(params object[] args) {
Console.WriteLine("Do more");
var nullableIntPairs = args.Where(IsNullableIntPair);
foreach (Pair<int> pair in nullableIntPairs) {
Console.WriteLine(pair.A);
Console.WriteLine(pair.B);
}
}
bool IsNullableIntPair(object arg) {
var type = arg.GetType();
return type.IsGenericType
&& type.GetGenericTypeDefinition() == typeof(Pair<>)
&& type.GetGenericArguments()[0] == typeof(int);
}
If you execute the following code
DoSomething(new Pair<int>(5, new int?()));
DoSomething(new Pair<long>(new long?(), 6L));
you get the following output:
Do more
5
null
Do more
You can use typeof :
a == typeof(Nullable<int>) //true
a == typeof(int) //false

What are Nullable Types in C#?

int? _fileControlNo = null;
public int? FileControlNo
{
get { return _fileControlNo; }
set { _fileControlNo = value; }
}
I'm getting a syntax error when I assign null values to the above properties.
objDPRUtils.FileControlNo =sArrElements.Value(3)==null ? null : Convert.ToInt32(sArrElements.Value(3));
Please, can anyone explain to me why the error occurs if I'm able to set null value in valuetype object using Nullable Type.
The results of the conditional operators need to be of the same type or types that can be implicitly convertible to each other.
In your case you have a null and an Int32 - these violate that requirement.
If instead of an Int32 you return a nullable Int32, the null can be implicitly converted to this type and your code will work (or alternatively, cast the null to an int?).
Cast your null to int?
objDPRUtils.FileControlNo =sArrElements.Value(3)==null ? (int?) null : Convert.ToInt32(sArrElements.Value(3));
The conditional operator needs to return result of the same type and in your case its not possible for null
this should work
sArrElements.Value(3)==null ? (int?)null : Convert.ToInt32(sArrElements.Value(3));
Nullable types are exactly what they say they are: simple value types that can also store a null value.
I would suggest that you do not need the last line of code at all. you should be able to get away with:
objDPRUtils.FileControlNo =sArrElements.Value(3);
If you really want to assign another value in case of null, use the null coalescing operator ??
objDPRUtils.FileControlNo =sArrElements.Value(3)??0;
which in this case, would assign the value 0 to the FileControlNo in case of the right hand side being null.
Try to assign directly like this :
objDPRUtils.FileControlNo =sArrElements.Value(3);
Your code mixes types null and Int32 cannnot be mixed in this instance like that. They need to be of the same type.
If you use int.TryParse and only attempt to set the value on success you will achieve the same result and can use HasValue on the field to determine if its null or not which is how nullable types are used typically
Silly example
class Program
{
private static int? _fileControlNo;
static void Main(string[] args)
{
string[] sArrElements = new string[] { "1", "2", "3", null };
int result;
if (int.TryParse(sArrElements[3], out result))
{
FileControlNo = result;
}
if (_fileControlNo.HasValue)
{
// do something here
}
}
public static int? FileControlNo
{
get { return _fileControlNo; }
set { _fileControlNo = value; }
}
}
you will note that your code inside the test for HasValue in this case will never execute because _fileControlNo cannot be set because tryParse always fails (change the indexer and that will change).

? (nullable) operator in C# [duplicate]

This question already has answers here:
What is the purpose of a question mark after a value type (for example: int? myVariable)?
(9 answers)
Closed 5 years ago.
What is changed by applying nullable Operator on value type datatype that now it can store null.
As others have said, "?" is just shorthand for changing it to Nullable<T>. This is just another value type with a Boolean flag to say whether or not there's really a useful value, or whether it's the null value for the type. In other words, Nullable<T> looks a bit like this:
public struct Nullable<T>
{
private readonly bool hasValue;
public bool HasValue { get { return hasValue; } }
private readonly T value;
public T value
{
get
{
if (!hasValue)
{
throw new InvalidOperationException();
}
return value;
}
}
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
// Calling new Nullable<int>() or whatever will use the
// implicit initialization which leaves value as default(T)
// and hasValue as false.
}
Obviously in the real code there are more methods (like GetValueOrDefault()) and conversion operators etc. The C# compiler adds lifted operators which effectively proxy to the original operators for T.
At the risk of sounding like a broken record, this is still a value type. It doesn't involve boxing... and when you write:
int? x = null;
that's not a null reference - it's the null value of Nullable<int>, i.e. the one where hasValue is false.
When a nullable type is boxed, the CLR has a feature whereby the value either gets boxed to a null reference, or a plain boxed T. So if you have code like this:
int? x = 5;
int y = 5;
object o1 = x;
object o2 = y;
The boxed values referred to by o1 and o2 are indistinguishable. You can't tell that one is the result of boxing a nullable type.
The ? syntax is syntactic sugar to the Nullable<T> struct.
In essence, when you write int? myNullableInt, the compiler changes it to Nullable<int> myNullableInt.
From MSDN (scroll down to "Nullable Types Overview"):
The syntax T? is shorthand for Nullable, where T is a value type. The two forms are interchangeable.
Nothing is changed on the value type itself, it's simply wrapped in a System.Nullable<T> struct.
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx
The type changes from what it used to be to a Nullable type.
If you had an int, and decided to make it an int?:
int myInt;
And you make it:
int? myInt;
it is now:
Nullable<int> myInt;
In reality.
In basic terms, a nullable type is a boxed version of the normal type that has an extra boolean field called hasValue on it.
When this field is set to false, then the instance is null.
Check out this answer for a bit more detail on the CLR implementation, and why they might have chosen it: Boxing / Unboxing Nullable Types - Why this implementation?

Categories

Resources