What are Nullable Types in C#? - 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).

Related

A default( T ) enum value doesn't equal null

I'm a bit surprised to find that calling the constructor in:
class MyClass<T>
{
public MyClass()
{
if ( default( T ) == null )
Debugger.Break();
}
}
doesn't break when T is an enum type. Why? It seems that even for enums, default( T ) and null should be equivalent.
No value type is ever going to test as equal to null, unless it's Nullable<T> which has special compiler and language support to treat an unset value as null.
The default(T) where T is any value type, including an enum, is going to be whatever the 0-filled value for that type is. I.e. an actual value. Not null.
Additional reading:
How to set enum to null
What does default(object); do in C#?
You may also want to read through some of the other hits in this search: [c#] default value enum null
Because enum in .net is a value type. If you only want to find out if default(T) == null then you can check if it is a reference type instead.
class MyClass<T>
{
public MyClass()
{
if (typeof (T).IsClass)
{
Debugger.Break();
}
else if (typeof (T).IsValueType)
{
//do something
}
}
}

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

Detect nullable type

Is it possible to detect a Nullable type (cast into an object) when it is null?
Since Nullable<T> is really a struct I think it should be possible.
double? d = null;
var s = GetValue(d); //I want this to return "0" rather than ""
public string GetValue(object o)
{
if(o is double? && !((double?)o).HasValue) //Not working with null
return "0";
if(o == null)
return "";
return o.ToString();
}
http://msdn.microsoft.com/en-us/library/ms228597(v=vs.80).aspx
Objects based on nullable types are only boxed if the object is
non-null. If HasValue is false, then, instead of boxing, the object
reference is simply assigned to null.
and
If the object is non-null -- if HasValue is true -- then boxing takes
place, but only the underlying type that the nullable object is based
upon is boxed.
So you either have a double or a null.
public string GetValue(object o)
{
if(o == null) // will catch double? set to null
return "";
if(o is double) // will catch double? with a value
return "0";
return o.ToString();
}
You have the method GetValueOrDefault for every Nullable type, isn't it enough ?
Your method currently takes object, which means the nullable value will be boxed... and will no longer be a nullable value. The value of o will either be a boxed value of the non-nullable type, or a null reference.
If at all possible, change your method to be generic:
public string GetValue<T>(T value)
{
// Within here, value will still be a Nullable<X> for whatever type X
// is appropriate. You can check this with Nullable.GetUnderlyingType
}
If o is null then o is double? will be false. No matter the value of your input parameter double? d
From what I understand, if you are trying to detect if ANY object is nullable, this can be written fairly easily.
try this...
public static bool IsNullable(dynamic value)
{
try
{
value = null;
}
catch(Exception)
{
return false;
}
return true;
}
Simple!

How to convert the following decimal? to String("F2")

I have Decimal? Amount
In my model I have a value as #item.Sales, which I`m trying to write as #item.Sales.ToString("F2").
I`m having the message error Error 1 No overload for method 'ToString' takes 1 arguments
How can I achieve the above
If it's a nullable decimal, you need to get the non-nullable value first:
#item.Sales.Value.ToString("F2")
Of course, that will throw an exception if #item.Sales is actually a null value, so you'd need to check for that first.
You could create an Extension method so the main code is simpler
public static class DecimalExtensions
{
public static string ToString(this decimal? data, string formatString, string nullResult = "0.00")
{
return data.HasValue ? data.Value.ToString(formatString) : nullResult;
}
}
And you can call it like this:
decimal? value = 2.1234m;
Console.WriteLine(value.ToString("F2"));
if( item.Sales.HasValue )
{
item.Sales.Value.ToString(....)
}
else
{
//exception handling
}
Use the unary ? operator to run .ToString() only when there's an object
#item.Sales?.ToString("F2")
Or use the double ?? operator thus makes it non-nullable:
#((item.Sales??0).ToString("F2"))
This is better than #item.Sales.Value.Tostring("F2") because if you don't check for null value before using .ToString("F2") the code will break at runtime.

Returning nullable string types

So I have something like this
public string? SessionValue(string key)
{
if (HttpContext.Current.Session[key].ToString() == null || HttpContext.Current.Session[key].ToString() == "")
return null;
return HttpContext.Current.Session[key].ToString();
}
which doesn't compile.
How do I return a nullable string type?
String is already a nullable type. Nullable can only be used on ValueTypes. String is a reference type.
Just get rid of the "?" and you should be good to go!
As everyone else has said, string doesn't need ? (which is a shortcut for Nullable<string>) because all reference types (classes) are already nullable. It only applies to value type (structs).
Apart from that, you should not call ToString() on the session value before you check if it is null (or you can get a NullReferenceException). Also, you shouldn't have to check the result of ToString() for null because it should never return null (if correctly implemented). And are you sure you want to return null if the session value is an empty string ("")?
This is equivalent to what you meant to write:
public string SessionValue(string key)
{
if (HttpContext.Current.Session[key] == null)
return null;
string result = HttpContext.Current.Session[key].ToString();
return (result == "") ? null : result;
}
Although I would write it like this (return empty string if that's what the session value contains):
public string SessionValue(string key)
{
object value = HttpContext.Current.Session[key];
return (value == null) ? null : value.ToString();
}
You can assign null to a string since its a reference type, you don't need to be able to make it nullable.
String is already a nullable type. You don't need the '?'.
Error 18 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'
string is already nullable on its own.

Categories

Resources