Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Errors, The Black Sheep of the Family

4.50/5 (4 votes)
13 Nov 2018CPOL10 min read 5.6K  
A look at the so called black sheep of the family of development, namely compiler errors and exceptions

Introduction

In this post, we will take a look at the so called “black sheep” of the family of development and those are errors, namely compiler errors and exceptions.

The reason I consider them as black sheep is that they often get a bad reputation even though the reason why they exist is to keep us aware and safe from the alternative. Consider them akin to what our bodies consider pain, if something hurts, then probably it’s bad for you, but not always.

Given the above mentioned, when you get an error or an exception, try to look as to why it happens, not just blindly implement a solution from the internet or a colleague, and in the case of exceptions, don’t just catch all and do nothing with the exception even though it might seem to fix the issue.

Not only should they be accepted, I also encourage using and throwing your own errors through the lifetime of your applications. And please don’t just throw a new Exception, take the time and either use a build in one or your own depending on the case.

First of all, I want to put out a disclaimer in that I have a strong aversion to generalization, that means everything we will be discussing in this post should be taken with a grain of salt, and use your better judgement where each applies.

Compiler Errors

We recently discussed this in the post about the use and abuse of keywords when we discussed why we can’t instantiate abstract classes. Now we will look at some common compiler errors and try to see if we can figure out what’s the reason behind them.

Operator ‘Operator’ Cannot Be Applied to Operands of type ‘type’ and ‘type’

In the old days (C++ and C) and in present times (JavaScript), you can use any value in an if clause and any value except null or 0 would mean true. But what does if(1) actually mean in the context of a code? It is not easy to understand since so many things can mean true, there is various uncertainty as to what you’re trying to do.

This error shows up when the compiler is confused about what are you trying to do. What does it mean when you try to add true with false, or if PersonA is greater than PersonB.

There are two ways around this error, one is using the proper syntax, like if you have a condition, make sure it evaluates to either true or false. The second way is to make the compiler understand what you mean, for example, if we need to compare PersonA with PersonB (or any other custom class), then you would have to implement a proper operator overload so that the compiler knows what your intentions are by comparing two classes or better said two types (like you could compare PersonA with a value of 18 and actually mean that it needs to compare the age, though if you really want to do that, why not implement a custom method and be explicit about it?).

Operator ‘operator’ is Ambiguous on Operands of type ‘type1’ and ‘type2’

This error is from the same family as the previous one, the compiler is confused about what you’re trying to achieve. For example, if you try to add BicicleA with CarB, what would the result be? What if you try to assign an instance of type Bridge to a variable of type Fridge?

This error has come to be due to two considerations, the first one would be semantic, does the operation you’re trying to do really make sense? The second consideration is the memory footprint, each type defines a template as to how much memory it takes and how it’s layed out, what each bit is part of. Of course, in memory, everything is bytes and bits but do they mean the same thing? Is it usable?

To get around this, you will have to make a cast and let the compiler know what your intentions are, and of course, if we’re discussing custom types, then you would need to implement either an explicit or implicit cast.

‘member’ is Inaccessible Due to its Protection Level

If we follow the advice that we discussed in use and abuse keywords part 1 of using the access modifier properly, then you will run into this error more often, but this just tells you that you’re breaking one of your own rules about properly encapsulating the members.

The solution for this is either elevate the permission of that member or better yet, consider why you need it there to begin with, might end up at the same resolution to elevate the permission, but it might also make you consider an alternative.

Control Cannot Fall Through from One Case Label (‘label’) to Another

This error is a little more specific to C# than other languages like Java or C++ (if I recall properly).

In those languages, you could have a switch that called a case and then fall through to another case due to a lack of termination of flow, like using return, break, throw, or continue.

Sometimes, that turned out beneficial but in most cases, it would cause an error down the line because the compiler did not have our back and stops us from doing something silly like forget a flow control.

Use of Unassigned Local Variable ‘name’

I remember when I was learning C++ in school and the fact that you needed to remember to initialize each and every variable you declared else, when you tried using it, it would end up spilling out garbage values (it was the actual memory that got emcompassed by that variable, but meh!).

Because of this compiler rule, I never had the issue of getting garbage values in my variables. Solution is easy, initialize your variables before using them or else the compiler won’t let you.

The Type or Namespace Name ‘type/namespace’ Could Not Be Found (Are You Missing a using Directive or an Assembly Reference?)

This error is very common amongst developers that type out what they want but forget to add a using statement. I admit since I have been using Resharper I have not had to deal with this issue as often.

The reason behind it is because we’re trying to use something that the compiler is not aware of.

Compiler Error Conclusion

For a full list of all of the compiler errors, you can find them here.

As an additional piece of advice for this, always turn on ‘warnings as errors’. The compiler also issues out warnings not just error, which sadly often ends up ignored because THE APPLICATION WORKS!!! but, remember when you refactored something and you ended up with that variable or field that is never used anymore? The compiler will complain but will still let you compile, though will you remember next time why you need that field or variable? Maybe not, because it’s not used presently so it brings no value.

Exceptions

These are errors that are thrown while the application is running and they are written to be thrown in explicit conditions. There are still systems out there that instead of throwing exceptions, return error codes, yuk! Imagine having a book or document of error codes used through the application and which code means what and how it happened.

Exception solve this issue, by providing the developer with more useful information (most of the time), like the message of the error, trying to explain why it happened and of course, the ever useful stack-trace which shows us what calls were made to end up in that scenario (though with stateful development, even that may not be enough).

If an exception happens, it is our jobs as developers to find out why it happened and if it’s unavoidable (like when trying to access a restricted file or we get a database timeout), what to do about it, maybe retry the operation, or maybe make a user friendly message and show it to the user letting them know why the operation failed, maybe because of faulty input or other issues that arose.

NullReferenceException

This is the most famous of the exceptions when trying to access the members of a class that have not been instantiated, then you can expect this error to show up. If you’re curious how common this exception is, try searching any code base for null checks (comparisons with null) and see how often you will find it. I can bet that most projects have at least 25% of the methods that include some kind of null check.

The exception has become so bad because even the .NET framework actually gives us more opportunities to check for them with the as operator or methods like TryParse and FirstOrDefault that either return a null themselves or a boolean instead of handling exceptions. Don’t get me wrong, those are needed but like with keywords, they sometimes end up being abused instead of actually fixing the root cause of an issue.

Here is a pattern that is all to common with overloaded methods and we will look at how they are encountered and how I think they should be handled.

C#
int ComputeTaxes(int stateId, Location location = null)
{
    if (location == null) { //do something...}
}

Now for the ways in which it should be handled, depending on the scenario, I see a few ways to handle it though it’s not a complete list.

C#
public int ComputeTaxes(int stateId, Location location)
{
    if (location == null) { location = new NullLocation(); }

    // or use the syntax location = location ?? new NullLocation();

    return ComputeTaxesInternal(state, location)
}

private int ComputeTaxesInternal(int stateId, Location location)
{

}

In this scenario, we are using the Null Object Pattern which lets us define an object that does nothing but also doesn’t throw an error. This helps us by avoiding the need to introduce null checks inside the calculation algorithm.

C#
public int ComputeTaxes(int stateId, Location location)
{
    if (location == null) 
       { throw new ArgumentNullException("location should not be null", "location"); }

    int taxes = ComputeTaxes(state);

    // do calculations on the location

    return taxes;
}

public int ComputeTaxes(int stateId) { //do logic here}

In this case, we throw an exception early and ensure that the prerequisites of the method works, and if now we know before any calculation is made that we have an issue further up the stream.

The conclusion for this exceptions is, use it, make it show you the flaws in design, don’t discard it or avoid it with null checks, if a collection has to contain an item, use the First method instead of the FirstOrDefault, if an object has to be convertible to a type, cast directly instead of using the as operator. The problem is why did we get a null reference exception, not how do we avoid it locally.

ArgumentNullException

This exception should be thrown as often as possible (of course if it’s required, don’t go zelot on it) when receiving parameters to a method, especially for library and framework developers, to one ensure that the method will work properly, and two to find the problems upsteam.

Exceptions Conclusion

I know this section had a lot less examples but there are a plethora of exceptions in the .NET Framework plus the ones you or your team will develop. I’m sure that by now, you have encountered more than your fair share of these exceptions.

Conclusion

Just because errors give us a slap on the wrist doesn’t mean that they are put there to make us feel stupid or punish us, they have some solid reasons for their existence and they should be understood and taken care of accordingly. So before going out to StackOverflow to find a solution for how to avoid an error, take the time and read up on its documentation, why it happens and then make the appropriate changes.

Thank you and I’ll see you next time.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)