if (list == null || list.Count == 0) return; if ((list?.Count ?? 0) == 0) return; if (!(list?.Count > 0)) return; // Something else?
Between these three, I'd prefer the first one. Although I wish there was a nicer way to use the null propagator here (is there?!?)...
Intro:
There are usually two ways to use linked lists: with a root element and without.
Without a root, your list pointer is NULL when the list is empty:
node *list;
...
if (list == NULL) { /* empty list */ }
With root, there is always one element. But it can be used in two ways:
Either simply to provide a pointer to the first element.
node *root;
...
if (root->next == NULL) { /* empty list */ }
Or to have the last element link back to the root to form a cycle. This concept has the advantage that the "next" element is never NULL and you thus don't need to check for it. In this case, the list is empty if the root points back to itself.
node *root;
...
if (root->next == root) { /* empty list */ }
Answer:
Now, according to your description, you have allocated a node. This either means you want the "root" approach (second or third example). But if you want to go with the first variant, you must not allocate the node, since it doesn't hold data.
For the "root" approach, you indeed have one (and only one) node that doesn't hold data. But for simple linked lists, all nodes must contain data.
I'd keep it simple.
Check the head pointer - if it is NULL, there's no entry in the list.
int isEmpty( node * list )
{
if( !list )
return 1;
return 0;
}
Try the following code:
if ( (myList!= null) && (!myList.Any()) )
{
// Add new item
myList.Add("new item");
}
A late EDIT because for these checks I now like to use the following solution. First, add a small reusable extension method called Safe():
public static class IEnumerableExtension
{
public static IEnumerable<T> Safe<T>(this IEnumerable<T> source)
{
if (source == null)
{
yield break;
}
foreach (var item in source)
{
yield return item;
}
}
}
And then, you can do the same like:
if (!myList.Safe().Any())
{
// Add new item
myList.Add("new item");
}
I personally find this less verbose and easier to read. You can now safely access any collection without the need for a null check.
And another EDIT, which doesn't require an extension method, but uses the ? (Null-conditional) operator (C# 6.0):
if (!(myList?.Any() ?? false))
{
// Add new item
myList.Add("new item");
}
For anyone who doesn't have the guarantee that the list will not be null, you can use the null-conditional operator to safely check for null and empty lists in a single conditional statement:
if (list?.Any() != true)
{
// Handle null or empty list
}
In C and C++, pointers are inherently unsafe, that is, when you dereference a pointer, it is your own responsibility to make sure it points somewhere valid; this is part of what "manual memory management" is about (as opposed to the automatic memory management schemes implemented in languages like Java, PHP, or the .NET runtime, which won't allow you to create invalid references without considerable effort).
A common solution that catches many errors is to set all pointers that don't point to anything as NULL (or, in correct C++, 0), and checking for that before accessing the pointer. Specifically, it is common practice to initialize all pointers to NULL (unless you already have something to point them at when you declare them), and set them to NULL when you delete or free() them (unless they go out of scope immediately after that). Example (in C, but also valid C++):
void fill_foo(int* foo) {
*foo = 23; // this will crash and burn if foo is NULL
}
A better version:
void fill_foo(int* foo) {
if (!foo) { // this is the NULL check
printf("This is wrong\n");
return;
}
*foo = 23;
}
Without the null check, passing a NULL pointer into this function will cause a segfault, and there is nothing you can do - the OS will simply kill your process and maybe core-dump or pop up a crash report dialog. With the null check in place, you can perform proper error handling and recover gracefully - correct the problem yourself, abort the current operation, write a log entry, notify the user, whatever is appropriate.
The other answers pretty much covered your exact question. A null check is made to be sure that the pointer you received actually points to a valid instance of a type (objects, primitives, etc).
I'm going to add my own piece of advice here, though. Avoid null checks. :) Null checks (and other forms of Defensive Programming) clutter code up, and actually make it more error prone than other error-handling techniques.
My favorite technique when it comes to object pointers is to use the Null Object pattern. That means returning a (pointer - or even better, reference to an) empty array or list instead of null, or returning an empty string ("") instead of null, or even the string "0" (or something equivalent to "nothing" in the context) where you expect it to be parsed to an integer.
As a bonus, here's a little something you might not have known about the null pointer, which was (first formally) implemented by C.A.R. Hoare for the Algol W language in 1965.
I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.
First of all you don't need double pointer. Initialization with NULL is important here. (Denotes the empty list).
SortedList *list = NULL;
This has the benefit that now if you want to make changes to it pass it's address.
func(&list);
And checking the empty list would be
void func(SortedList **list){
if( *list == NULL )
/* empty */
}
This is usually the way lists are implemented.
In your case you simply allocated to a local variable and instead of returning the memory address you have overwritten the pointer's value with NULL - there is memory leak in the code.
With your code it will be something like. Yes all that the initialization does is assigning it to NULL. This is one easy way out towards checking the NULL. At the very beginning making it NULL
basically denotes that list is empty.(which is the case generally).
list is a pointer to a pointer. The actual list is in the value it points to, so you need to dereference it.
An empty list is just a null pointer, so you don't need to allocate anything in init().
void init(SortedList** list)
{
*list=NULL;
printf("%p\n", *list);
}
void isEmpty(SortedList** list)
{
printf("%p\n", *list);
if(*list == NULL) printf("List is empty\n");]
}
And in the main function, you don't need a double pointer, you use the & (address-of) operator to get the address of a pointer variable.
int main()
{
SortedList *list;
init(&list);
printf("Initialization with succes\n");
isEmpty(&list);
return 0;
}
You only really need double pointers for functions that modify the list. So you could use an ordinary pointer for isEmpty:
void isEmpty(SortedList* list)
{
printf("%p\n", list);
if(list == NULL) printf("List is empty\n");]
}
and then call it as:
isEmpty(list);
But it's probably simplest to be consistent across all your functions.
What do you mean with empty?
When a C program is executed, variables that you don't explicitly initialize have got unpredictable values.
You need to set all of your array cells to NULL (or to 0, or to whatever value represents emptyness in your program logic) and then you can check it in the way you did:
int *array[3] = { NULL, NULL, NULL }; // array of three "empty" pointers
...
for( i = 0; i < 3; ++ i ) {
if( array[i] == NULL ) {
// i-th cell is "empty"
}
}
Question answer:
What you posted is the correct code.
Elaboration:
If it "doesn't seem to work", perhaps the problem does not lie at this location in your code. If you would post a more complete example of what you have, the code's expected behavior and actual behavior, we may be able to help you.
Generally, your lists should always be initialized. One common misconception is that queries can produce a null list, which is never true.
For example, consider the following code:
Account[] records = [SELECT Id, Name, AccountNumber FROM Account];
if(records!=null && !records.isEmpty()) {
for(Account record: records) {
// Do Something Here
}
}
This is a waste of CPU time, because (a) records will never be null, and (b) iterating over an empty list is acceptable. Therefore, none of the three checks you might use are rarely appropriate. The only exception to this rule is when one query is used to fuel another query, in which case you would check for the presence of values before performing the query:
Account[] accounts = [SELECT Id, Name, AccountNumber FROM Account];
if(accounts.isEmpty()) {
return;
}
Contact[] contacts = [SELECT Id, Name, Email FROM Contact WHERE AccountId IN :accounts];
For lists you create yourself, you should always initialize them before using them. This is true for other types, like sets and maps, as well. There are, however, times when you'll need to check for a specific condition before using some lists. It helps if you experiment with the various types to get a feel for when you should be aware that a list may be null.
For example, consider a variable that binds to a multi-select picklist:
public String[] selectedValues { get; set; }
In this case, selectedValues will either be null, or will not be empty. You only ever need to check for != null in this case. Part of becoming an efficient developer is recognizing the patterns in a system. If you're still using myVar != null && !myVar.isEmpty() as a condition, that generally means you're making one or even two checks too many.
There is always one correct condition to use in every situation. If this isn't true, that suggests that values were not properly initialized elsewhere.
Edit: Safe Navigation Operator
As a special exception, you can now use the Safe Navigation Operator to skip the null check. That looks like this:
if(records?.size() > 0) {
/* Do something here */
}
Because of the changes brought in with the Safe Navigation Operator, when either size of the comparison is null, the result is false. If we want to abort early, then we can negate the entire thing:
if(!(records?.size() > 0)) {
return;
}
It is generally best to avoid null values in code so using null list references to indicate empty lists isn't usually good approach. That is this code:
List<String> strings = new List<String>();
...
for (String item : strings) {
...
}
is clearer and safer than this code:
List<String> strings = null;
...
if (strings != null) {
for (String item : strings) {
...
}
}
So prefer empty lists to null list references.
Personally I find myList.size() > 0 to be clearer than !myList.isEmpty() because the latter amounts to "not is empty" which takes a moment to understand. But as people will use both forms get used to both.
Why do List not have a general Empty or IsEmpty property?