Sorry for this awkward example, but I want to keep it as to the point as possible
Lets say, I have parsed a json-file, which gives me the hierarchy below
var customers = myObj.SubObj?.CustomerList.EmptyIfNull();
var plusCustomers = customers.Where(...) // Resharper warning
myobj cannot be null
SubObject can be null sometimes
I have an extension method
IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable) => enumerable ?? Enumerable.Empty<T>();
So I expect the plusCustomers-line to be safe(empty list instead of null). But I get a warning
possible "null"assignment to a non-nullable entity
If I replace the first line with
var customers = myObj.SubObj.CustomerList.EmptyIfNull();
I get rid of the warning, but that is not correct. How can I convince Resharper that this is ok?...or I'm I mistaken?
You can add brackets:
(myObj.SubObj?.CustomerList).EmptyIfNull();
The effect of the null chaining (?.) is to evaluate the whole chain of member accesses to null, if the LHS operand is null, rather than evaluating just that single member access to null. For example, consider a long chain of member accesses a.b.c.d.e.f. If only a is nullable, you would only need to write ? after a for this to be safe. It doesn't just evaluate a?.b to null if a is null, because in that case you'd have to write ? after every member access for this to be safe, and that's a bit annoying.
So without the brackets, the whole member access is made nullable due to ?., regardless of what you call at the end.
By adding brackets, you break up the chain of member accesses, so that myObj.SubObj?.CustomerList is of a nullable type, and calling EmptyIfNull on that works as expected - returning whatever type EmptyIfNull should return.
Related
After seeing a similar question, I was wondering if the following expression ...
if (attribute != null && attribute.Description == input)
... would behave (almost) identical, to following null-propagation variant?
if (attribute?.Description == input)
So far, I could determine only following (somehow minor) differences:
not possible in case input is of non-nullable type
in case input would be itself null, behavior would be altered
Am I missing something? or are there other differences in behavior?
EDIT: in the end, the only fail-safe alternative I've found for the first snippet, would be:
if (attribute?.Description?.Equals(input) ?? false)
The code will work if input is of a non-nullable type. There is an implicit conversion of all non-nullable types to their nullable counterparts, so input will simply be lifted to a nullable to be compared to the property value.
The only difference in behavior, as you mentioned is that, if input is null, then the second snippet has no way of differentiating between attribute being null, when it should be false, and where Description is null, where it should be true.
Oh, and this is assuming that attribute is a local variable or field. If it's a property (or is actually a more complex expression) then it could have side effects or result in a different value when computed twice, as happens in the first snippet but not the second, which is a difference in behavior.
This is all of course assuming a single threaded context. In a multithreaded context, if attribute is accessible from another thread (either because it's a field that's accessible or because it's closed over in a lambda that is exposed to another thread) then the value could be different each time it's computed, so the two snippets differ for the same reason described in the previous paragraph.
Could someone please be kind enough to explain why calling ToString() on an empty reference type causes an exception (which in my mind makes perfect sense, you cant invoke a method on nothing!) but calling ToString() on an empty Nullable(Of T) returns String.Empty? This was quite a surprise to me as I assumed the behaviour would be consistent across types.
Nullable<Guid> value = null;
Stock stock = null;
string result = value.ToString(); //Returns empty string
string result1 = stock.ToString(); //Causes a NullReferenceException
Nullable<T> is actually a struct that has some compiler support and implementation support to behave like a null without actually being null.
What you are seeing is the collision between the implementation allowing you to treat it naturally as a null as you would any other reference type, but allowing the method call to happen because the Nullable<T> isn't actually null, the value inside it is null.
Visually it looks like it shouldn't work, this is simply because you cannot see what is done in the background for you.
Other such visual trickery can be seen when you call an extension method on a null reference type... the call works (against visual expectation) because under the hood it is resolved into a static method call passing your null instance as a parameter.
How does a Nullable<T> type work behind the scenes?
Nullable is a value type and the assignment to null causes it to be initialized with Value=null and HasValue=false.
Further, Nullable.ToString() is implement as follows:
public override string ToString()
{
if (!this.HasValue)
{
return "";
}
return this.value.ToString();
}
So what you are seeing is expected.
It is a bit tricky with nullable types. When you set it to null it is actualy not null cause it is not reference type (it is value type). When you initialize such variable with null it creates new sctructure instance where HasValue property is false and it's Value is null, so when you call ToString method it works well on structure instance.
The exception raised by calling default(object).ToString() is called NullReferenceException for a reason, it's calling a method on a null reference. default(int?) on the other hand, is not a null reference, because it's not a reference; it is a value type with a value that is equivalent to null.
The big practical point, is that if this was done, then the following would fail:
default(int?).HasValue // should return false, or throw an exception?
It would also screw-up the way we have some ability to mix nullables and non-nullables:
((int?)null).Equals(1) // should return false, or throw an exception?
And the following becomes completely useless:
default(int?).GetValueOrDefault(-1);
We could get rid of HasValue and force comparison with null, but then what if the equality override of the value-type that is made nullable can return true when compared to null in some cases. That may not be a great idea, but it can be done and the language has to cope.
Let's think back to why nullable types are introduced. The possibility that a reference type can be null, is inherent in the concept of reference types unless effort is taken to enforce non-nullability: Reference types are types that refer to something, and that implies the possibility of one not referring to anything, which we call null.
While a nuisance in many cases, we can make use of this in a variety of cases, such as representing "unknown value", "no valid value" and so on (we can use it for what null means in databases, for example).
At this point, we've given null a meaning in a given context, beyond the simple fact that a given reference doesn't refer to any object.
Since this is useful, we could therefore want to set an int or DateTime to null, but we can't because they aren't types that refer to something else, and hence can't be in a state of not referring to anything any more than I as a mammal can lose my feathers.
The nullable types introduced with 2.0 give us a form of value types that can have the semantic null, through a different mechanism than that of reference types. Most of this you could code yourself if it didn't exist, but special boxing and promotion rules allow for more sensible boxing and operator use.
Okay. Now let's consider why NullReferenceExceptions happen in the first place. Two are inevitable, and one was a design decision in C# (and doesn't apply to all of .NET).
You try to call a virtual method or property, or access a field on a null reference. This has to fail, because there's no way to look up what override should be called, and no such field.
You call a non-virtual method or property on a null reference which in turn calls a virtual method or property, or accesses a field. This is obviously a variant on point one, but the design decision we're coming to next has the advantage of guaranteeing this fails at the start, rather than part-way through (which could be confusing and have long-term side-effects).
You call a non-virtual method or property on a null reference which does not call a virtual method or property, or access a field. There's no inherent reason why this should not be allowed, and some languages allow it, but in C# they decided to use callvirt rather than call to force a NullReferenceException for the sake of consistency (can't say I agree, but there you go).
None of these cases apply in any way to a nullable value type. It is impossible to put a nullable value type into a condition in which there is no way to know which field or method override to access. The whole concept of NullReferenceException just doesn't make sense here.
In all, not throwing a NullReferenceException is consistent with the other types - types through it if and only if a null reference is used.
Note that there is a case where calling on a null nullable-type throws, it does so with GetType(), because GetType() is not virtual, and when called on a value-type there is always an implied boxing. This is true of other value types so:
(1).GetType()
is treated as:
((object)1).GetType()
But in the case of nullable types, boxing turns those with a false HasValue into null, and hence:
default(int?).GetType()
being treated as:
((object)default(int?)).GetType()
which results in GetType() being called on a null object, and hence throwing.
This incidentally brings us to why not faking NullReferenceType was the more sensible design decision - people who need that behaviour can always box. If you want it to through then use ((object)myNullableValue).GetString() so there's no need for the language to treat it as a special case to force the exception.
EDIT
Oh, I forgot to mention the mechanics behind NullReferenceException.
The test for NullReferenceException is very cheap, because it mostly just ignores the problem, and then catches the exception from the OS if it happens. In other words, there is no test.
See What is the CLR implementation behind raising/generating a null reference exception? and note how none of that would work with nullable value types.
If you investigate Nullable<> definition, there is an override ToString definition. In this function, ToString is overriden to return String.Empty.
// Summary:
// Returns the text representation of the value of the current System.Nullable<T>
// object.
//
// Returns:
// The text representation of the value of the current System.Nullable<T> object
// if the System.Nullable<T>.HasValue property is true, or an empty string ("")
// if the System.Nullable<T>.HasValue property is false.
public override string ToString();
On the otherhand, Stock is a custom class, which I assume ToString is not overriden. Thus it returns NullReferenceException since it uses default behaviour.
As per MSDN Remarks
Guid.ToSTring() method Returns a string representation of the
value of this Guid instance, according to the provided format
specifier.
As per MSDN Remarks on Nullable
A type is said to be nullable if it can be assigned a value or can be
assigned null, which means the type has no value whatsoever.
Consequently, a nullable type can express a value, or that no value
exists. For example, a reference type such as String is nullable,
whereas a value type such as Int32 is not. A value type cannot be
nullable because it has enough capacity to express only the values
appropriate for that type; it does not have the additional capacity
required to express a value of null.
I use following Linq To Entitiy To get the first and only record of my 'siteconfig' Entity :
var site = unitofwork.SiteConfigRepository.Get().FirstOrDefault();
But when my application comes to the following code, throws 'nullable object must have a value' :
if (site!= null) { TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate ); }
And the only nullable type in my entity is a property called logindDate and is of type DateTime.
Any one help me out?
Try something like this:
if (site!= null)
{
if (site.loginDate.HasValue)
{ TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate.Value ); }
}
You are not checking for a null loginDate and I suspect that may be the problem. Remember, when you have a nullable type, you need to check for HasValue, and then get the value from the Value property.
IEnumerable.FirstOrDefault() returns the first element of the enumerable, or default(T) (which is generally null, unless T is a value type) if there is no element in the list. Most probably your Get() returns an empty enumerable.
On a related matter (if indeed it is what happens), if you're sure that there is always one and only one element returned by a list, you should use Single() (because then you will have an exception thrown at that line) or test it against null just after the FirstOrDefault(). I think it's best having exceptions throwing or handling at the source of the unexpected behavior, and not several lines later.
When I was writing C# code a few days ago I noticed that the compiler complained that I had to cast null to a specific object.
Does this mean that null is simply an uninstantiated version of the type? Or is it a singleton value of a Null class like Java (even though it has special privileges)?
EDIT: an example of the code giving the error would be:
public String duplicate(String toDuplicate)
{
return toDuplicate + toDuplicate;
}
public String duplicate(int? toDuplicate)
{
String asString = toDuplicate.toString();
return asString + asString;
}
public static int Main(string[] args)
{
//This needs to be cast:
duplicate(null);
//To:
duplicate((string)null);
}
The reason I commented on null in Java was after reading this:
There is also a special null type, the
type of the expression null, which has
no name. Because the null type has no
name, it is impossible to declare a
variable of the null type or to cast
to the null type. The null reference
is the only possible value of an
expression of null type. The null
reference can always be cast to any
reference type. In practice, the
programmer can ignore the null type
and just pretend that null is merely a
special literal that can be of any
reference type.
Found here: Is null an Object?
I get the error you refer when i have overloaded methods and the compiler can't resolve which method to call at compile time. Is that it?
According to the MSDN description:
The null keyword is a literal that represents a null reference, one that does not refer to any object. null is the default value of reference-type variables. Ordinary value types cannot be null. However, C# 2.0 introduced nullable value types.
null is the "uninstanciated reference" for any type. It is not a value. null has no defined type.
No - the null is just a literal for the null reference.
The reason you need to "cast" it in this way (I put the word cast in quotes because you are not really casting an instance of anything), is purely to help the compiler resolve which overload of a method you are calling, or the method you are calling even exists.
In your example, you need to specify that you are calling the method "duplicate" that takes a single string argument. If you omit the cast, then the compiler only knows that the method you intended to call is called "duplicate" and has a single argument, but can't tell what type the argument is - did you mean to call duplicate(string) or did you mean to call duplicate(some other type)? Should it compile, or should it error telling you the method you are trying to call does not exist?
You will also get the same issue if you had a duplicate(byte[]) defined, because now your call is ambiguous without the explicit cast.
No its not an object. null is the default value of reference-type variables. Ordinary value types cannot be null. but there is another set called nullable types.
You are probably referring to the fact that the following leads to a compiler error:
int? nullableInt = (somecondition) ? value : null;
Indeed you need to add a cast here:
int? nullableInt = (somecondition) ? value : (int?)null;
Even though I'm not able to explain this in detail, I'd suspect the following:
int? is actually a short form for Nullable<int>, so it is basically an object instance. When assigning an int value to nullableInt, a property of Nullable<int> will be set internally. Directly assigning null would also be ok.
The conditional assignment however, would return two different types: int in case somecondition is true and object (null) otherwise.
Now the compiler doesn't know how to handle this, as the ternary operator needs to return values of the same type. So you need to specify the desired "type for the null value".
Sorry if this is not a very deep technical explanation - I'm sure there's somebody who can elaborate this better, but it might help understand this better.
If I have a long list of objects that each has the possibility of returning null within a "Linq where" clause, e.g.
SomeSource.Where(srcItem=>(srcItem.DataMembers["SomeText"].Connection.ConnectedTo as Type1).Handler.ForceInvocation == true));
the indexer can return null and the "as" operator may return null. It is possible that the object does not have a connection (ie. The property is null).
If a null is encountered anywhere, I would like the where clause to return "false" for the item being evaluated. Instead, it aborts with a null reference exception.
It appears to me that this would be contrived to express within a single C# expression. I don't like to create a multi line statement or create a separate func for it.
Is there some use of the null coalescing operator that I'm missing?
You're looking for the .? operator (or is it ?.—one of those, anyway), which does not exist in C# (though it is an often-requested feature, according to Eric Lippert).
The only possible suggestion I have is to write a method that takes an expression and uses it to check for any nulls. But this will come at a performance cost. Anyway, it might look like:
T TryOrDefault<T>(Expression<Func<T>> expression)
{
// Check every MemberExpression within expression one by one,
// looking for any nulls along the way.
// If a null is found, return default(T) or some default value.
// Otherwise...
Func<T> func = expression.Compile();
return func();
}
Using the andand operator from Ruby as inspiration, you could create an extension method that acts as a null guard.
public static U AndAnd<T, U>(this T obj, Func<T, U> func)
{
return obj == null ? default(U) : func(obj);
}
Your original code could then be rewritten as follows:
SomeSource.Where(srcItem => (srcItem.AndAnd(val => val.DataMembers["SomeText"]).AndAnd(val => val.Connection).AndAnd(val => val.ConnectedTo) as Type1).AndAnd(val => val.Handler).AndAnd(val => val.ForceInvocation));
Do be careful when returning non-boolean value types using this method - make sure you are familiar with the values returned by default(U).
create a separate func for it
This is the way to go. Do not be allergic to proper techniques. Methods you create are no more expensive (at runtime, and conceptually) than anonymous methods.
A while ago I wrote a project that mimics AndAnd that relies on DynamicProxy. It works fine, although I've not used it in prod. The only drawback is that it requires all of the members to be virtual or the returned types to be an interface so DynamicProxy can do its magic.
Check it here
https://bitbucket.org/mamadero/andand/overview