C# Testing for null - c#

I'm using C# to write a simple program to read Active Directory and display the value held in a AD field on a Windows form program.
If a property doesn't exist then the program crashes, below is my code, how can I catch this and move on to the next field without doing a try/catch for each and every attribute?
DirectoryEntry usr = new DirectoryEntry("LDAP://" + domain, username, password);
DirectorySearcher searcher = new DirectorySearcher(usr);
searcher.Filter = "(sAMAccountName=" + GlobalClass.strUserName + ")";
searcher.CacheResults = false;
searcher.SearchScope = SearchScope.Subtree;
searcher.PropertiesToLoad.Add("givenName");
searcher.PropertiesToLoad.Add("telephoneNumber");
//program crashes here if telephoneNumber attribute doesn't exist.
textBoxFirstName.Text = usr.Properties["telephoneNumber"].Value.ToString();

Just checking usr.Properties["telephoneNumber"] will not work. You must check the actual value. The reason the error is occuring is because you're calling ToString() on Value which is null.
user.Properties will always return a PropertyValueCollection, regardless of the property name entered into the collections indexer.
I.e.
var pony = usr.Properties["OMG_PONIES"]; // Will return a PropertyValueCollection
var value = pony.Value; // Will return null and not error
You need to check the value itself, the best way through the null coalescing operator:
textBoxFirstName.Text = (usr.Properties["telephoneNumber"].Value
?? "Not found").ToString();

Store the contents of usr.Properties["telephoneNumber"]; in a variable and check for null:
PropertyValueCollection tel = usr.Properties["telephoneNumber"];
textBoxFirstName.Text = (tel != null && tel.Value != null)
? tel.Value.ToString()
: "";

Use the null-coalescing operator (??) operator.
textBoxFirstName.Text = (usr.Properties["telephoneNumber"].Value
?? String.Empty).ToString();
This way the value is replaced with an empty string if null. You could also just return null instead of String.Empty, the reason your code is crashing is because you're trying to call ToString() on a null value.

Something like this should work. If telephoneNumber is not null, it will convert the value to a string, otherwise it will use an empty string.
textBoxFirstName.Text = usr.Properties["telephoneNumber"].Value != null
? usr.Properties["telephoneNumber"].Value.ToString()
: "";

A couple of things will help this be more graceful:
Test usr.Properties["telephoneNumber"] for null before calling child properties like Value. I haven't worked with AD myself, but most string-keyed indexers are designed to gracefully handle non-existent keys. the CLR, on the other hand, will happily throw a NullReferenceException any time you try to reference a member of anything that evaluates to null.
On the off chance that AD DOES blow up on a nonexistent column, enclose the assignment in a Try-Catch block that will show an error on the screen and gracefully continue processing (or not).

Use this code
SearchResult.Properties.Contains("property")
To check if the object actually has the prop loaded from the search result

if (usr.Properties["telephoneNumber"] != null)
textBoxFirstName.Text = usr.Properties["telephoneNumber"].Value.ToString();

Related

Excel IsError equivalent function in C#

Is there a function in c# that can help to check if the statement is going to return error.
I am aware about try{} catch{} but we can't use it in condition checking. For example:
var opertionResult = SomeRestFunction.Trigger();
string ServerResponse = if(operationResult != null)
{
if(operationResult.Response != null)
{
operationResult.Response.ResponseText;
}
Else
{
"Null";
}
}
Else
{ "Null"; }
In the example above, I need to perform multiple checks to validate the operationResult object properties at multiple levels due to nested objects in it, to determine the final value I want to read and consume as server response value.
If we have some thing like IsError() function in Excel, we can simply try to read the final object property i.e. operationResult.Response.ResponseText; inside of that function and if any of the parent object is null and it has to throw an error it will return false and we can return the value from the else block as shown in the hypothetical example below:
var opertionResult = SomeRestFunction.Trigger();
string ServerResponse = IsError(operationResult.Response.ResponseText)? "Null": operationResult.Response.ResponseText;
So, do we have something like this in C#? Hope this makes sense?
If you're using c# 6 or newer version then you can use null-conditional & null-coalescing-operator operator like below.
Here you need to place ? to check if object is null or not. If object is null then it will not perform any further check and return null. And null-coalescing-operator (??) will be used to check if value is null then it will return value provided afer ??.
string ServerResponse = SomeRestFunction.Trigger()?.Response?.ResponseText ?? "Null";

Why doesn't a null cause a NullReferenceException when mapping to and from a null type?

I'm basically trying to iterate over a lot of data and transform a returned data query to a more limited object within a View Model.
Rather than do a huge section of code, I'm calling .ForEach() on a list, then adding a new entry to the view model's list.
This works great, but, there is one property (Address) that is optional.
When I reach the optional item, I get NullReferenceException if the item from the DB doesn't have an entry.
A code example is:
var tmp = _context.Person.Include(x => x.Address).ToList();
tmp.ForEach(x => vm.List.Add(new IndexListItem()
{
Name = x.Name,
Address = x.Address.FirstLine + " " + x.Address.SecondLine,
ID = x.ID
}));
I have since found out from a different answer on this site that if I change the address line so that it reads:
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
The code now works when I hit a null entry in tmp.
I do not understand this as the Address property on tmp was already allowing nulls, and the Address property on the view model allows nulls, so, why does changing the line suddenly not return an error?
In addition, is the reason for me not having to do x.Address?.FirstLine? because that's a string and strings are already nullable?
A null reference exception in this particular case is caused when you are trying to access a property where the parent object is null itself.
x.Address.FirstLine
i.e. in your case Address is null.
It is not in regard to what you are trying to set (i.e. the destination view model).
The reason that this works:
x.Address?.FirstLine
..is because 'in the background' it's checking first to see if Address is null. If it isn't, then it returns FirstLine and if it is, then null is returned. It's semantically equivalent to:
if (x.Address == null)
{
return null;
}
else
{
return x.Address.FirstLine;
}
Here's a blog post about the introduction of the ?. operator in C# for some background reading: https://blogs.msdn.microsoft.com/jerrynixon/2014/02/26/at-last-c-is-getting-sometimes-called-the-safe-navigation-operator/
I do not understand this as the Address property on tmp was already allowing nulls, and the Address property on the view model allows nulls, so, why does changing the line suddenly not return an error?
You are mixing up saving data with loading data. When you save the data to the database, null is acceptable, but when you try to use the data, null is not.
The null conditional operator (?.) allows you to "shorten" an if statement, and it would be something similar to:
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
string Address = "";
if (x.Address != null)
{
Address += x.Address.FirstLine;
}
// ....
Also, while not relevant to your problem, the code you are using is extremely ineffective, you are loading 2 tables to get just a few properties when you could get those properties directly from the database:
var vm = _context.Person
.Select(x => new IndexListItem
{
Name = x.Name,
Address = x.Address?.FirstLine + " " + x.Address?.SecondLine,
ID = x.ID
})
.ToList();
x.Address?.FirstLine where ? is null propogation operator this means if x.Address is null set null for the FirstLine.
null propogation equivalent code
if (x.Address == null)
return null
else
return x.Address.FirstLine
All reference type variables are nullable. hence, assigning null to reference types are always valid.
string is a reference-type in your example. therefore you do not get error because string x = null is valid
Your issue isn't that Address is null and you're trying to assign it to another property that allows null, it's that you're trying to access .FirstLine in something that's null.
If Address is null, then what you're trying to do with .FirstLine is the equivalent of null.FirstLine which doesn't work. Nothing can't hold something.
The ? notation you're using that works is only effecting Address, basically saying if Address is NOT null give me the value of .FirstLine, if it is null, then give me null.

Proper null check

I am instantiating an Associate object and assigning properties to it from txtboxes inside of my main form. What is the best practice for null checking? Is it to check each and every property with an if statement before I assign it or is there something a bit better? Here is my code:
Associate updateAssociate = new Associate();
updateAssociate.AssocID = txtAssocId.Text;
updateAssociate.FirstName = txtFname.Text;
updateAssociate.LastName = txtLname.Text;
updateAssociate.HireDate = Convert.ToDateTime(txtHireDate.Text);
updateAssociate.ContractEndDate = Convert.ToDateTime(txtContractEnd.Text);
updateAssociate.TerminationDate = Convert.ToDateTime(txtTerminationDate.Text);
updateAssociate.FullPartTimeID = cboFullPart.SelectedText;
updateAssociate.PrimaryRole = cboPRole.SelectedText;
Based on your comment to the question:
If it is a text box then it would be the .Text property I would want to check for null or blank values before I assign them to the object
You can use the null coalescing operator to check for null values when assigning like that:
updateAssociate.AssocID = txtAssocId.Text ?? string.Empty;
or:
updateAssociate.AssocID = txtAssocId.Text ?? someDefaultValue;
That way if txtAssocId.Text is null then you would assign your defined default to the object property instead of null.
Though I'm not entirely sure a TextBox's .Text property would ever be null instead of an empty string. Maybe you want to check for both?:
updateAssociate.AssocID = string.IsNullOrEmpty(txtAssocId.Text) ? someDefaultValue : txtAssocId.Text;
In C# 6 it would be null-conditional operator.
updateAssociate.AssocID = txtAssocId?.Text;
In prior versions of c# you can write a method to eliminate code duplication. Something like this:
public static T CheckNull<T>(Func<T> canBeNull) where T : class
{
try
{
return canBeNull();
}
catch (NullReferenceException)
{
return default(T);
}
}
And use it like this
updateAssociate.AssocID = CheckNull(() => txtAssocId.Text);
Then you can wrap any code that can throw a null reference into lambda, pass it to this method and no longer bother with it.

Null Linq Values

I cant get this to work. The State field is empty on certain occassions, I am trying to get the result to return "--" if it is empty, or doesn't exist.
var CusipFields = from c in xml.Descendants("LISTARRAY")
orderby c.Element("ASKYIELD").Value descending
select new BondData()
{
CUSIP = c.Element("CUSIP").Value,
Description = (string)c.Element("ISSUER").Value,
Maturity= c.Element("MATURITYDT").Value,
AskYield = float.Parse(c.Element("ASKYIELD").Value),
State = (string)c.Element("STATE").Value ?? "--"
}
;
This just doesn't want to work. The error I am getting is:
NullReferenceException was unhandled. {"Object reference not set to an instance of an object."}
I KNOW that it does not exist. I thought that putting ?? "--" will return "--" if c.Element("STATE").Value is null.
I can resort to modifying the statement to:
var CusipFields = from c in xml.Descendants("LISTARRAY")
orderby c.Element("ASKYIELD").Value descending
select c;
foreach(var t in CusipFields)
{
switch(t.name)
{
}
}
But I think that it is slower. And its not what I want.
Use this:
State = (string)c.Element("STATE") ?? "--"
instead of
State = (string)c.Element("STATE").Value ?? "--"
My answer assumes, that your problem is, that the STATE element is missing, not empty. Please tell me, whether or not that fixed your problem.
I think it's because c.Element("STATE") is null, not it's Value property.
try:
(string)c.Element("STATE") != null? (string)c.Element("STATE").Value : "--";
You're getting this error not because the Value property is null, but because c.Element(...) is null. You'll need to check for nulls in all of your Element() calls and take appropriate action in order to avoid this error.

How to assign a value of a property to a var ONLY if the object isn't null

In my code, is there a shorthand that I can use to assign a variable the value of a object's property ONLY if the object isn't null?
string username = SomeUserObject.Username; // fails if null
I know I can do a check like if(SomeUserObject != null) but I think I saw a shorthand for this kind of test.
I tried:
string username = SomeUserObject ?? "" : SomeUserObject.Username;
But that doesn't work.
Your syntax on the second is slightly off.
string name = SomeUserObject != null ? SomeUserObject.Username : string.Empty;
In c# 6.0 you can now do
string username = SomeUserObject?.Username;
username will be set to null if SomeUSerObject is null.
If you want it to get the value "", you can do
string username = SomeUserObject?.Username ?? "";
The closest you're going to get, I think, is:
string username = SomeUserObject == null ? null : SomeUserObject.Username;
This is probably as close as you are going to get:
string username = (SomeUserObject != null) ? SomeUserObject.Username : null;
You can use ? : as others have suggested but you might want to consider the Null object pattern where you create a special static User User.NotloggedIn and use that instead of null everywhere.
Then it becomes easy to always do .Username.
Other benefits: you get / can generate different exceptions for the case (null) where you didn't assign a variable and (not logged in) where that user isn't allowed to do something.
Your NotloggedIn user can be a derived class from User, say NotLoggedIn that overrides methods and throws exceptions on things you can't do when not logged in, like make payments, send emails, ...
As a derived class from User you get some fairly nice syntactic sugar as you can do things like if (someuser is NotLoggedIn) ...
You're thinking of the ternary operator.
string username = SomeUserObject == null ? "" : SomeUserObject.Username;
See http://msdn.microsoft.com/en-us/library/ty67wk28.aspx for more details.
It is called null coalescing and is performed as follows:
string username = SomeUserObject.Username ?? ""

Categories

Resources