Avoiding unnecessary links

Apparently, the vast majority of errors in the code are null reference exceptions. Are there any general methods to avoid collisions with zero reference errors?

If I am wrong, I know that in languages ​​like F # it is impossible to get a null value. But this is not a question, I ask how to avoid zero reference errors in languages ​​such as C #.

+19
c # exception nullreferenceexception
Dec 22 '09 at 0:17
source share
15 answers

When a null reference exception is displayed to the user, this indicates a code defect caused by an error on the part of the developer. Here are some ideas on how to prevent these errors.

My main recommendation for people who care about software quality and also use the .NET programming platform is to install and use Microsoft code contracts ( http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx ) . It includes runtime and static validation capabilities. A significant opportunity to create these contracts in your code is included in version 4.0. If you're interested in the quality of the code, and it sounds like you, you might really enjoy using Microsoft code contracts.

With Microsoft code contracts, you can protect your method from null values ​​by adding preconditions like this "Contract.Requires (customer! = Null);". Adding a precondition like this is equivalent to the practice recommended by many others in their comments above. Prior to code contracts, I would recommend you do something like this.

if (customer == null) {throw new ArgumentNullException("customer");} 

Now i recommend

 Contract.Requires(customer != null); 

Then you can activate the runtime verification system, which will catch these defects as soon as possible, which will lead you to diagnose and fix the defective code. But don't let me give the impression that code contracts are just a fancy way of replacing null arguments. They are much stronger. With Microsoft code contracts, you can also run a static check and ask her to examine possible sites in your code where null-reference exceptions may occur. Static validation requires a little more experience to use. I would not recommend it first for beginners. But feel free to try and see for yourself.

NULL REFERENCE ERROR DISTRIBUTION STUDY

There has been some debate in this thread about whether null reference errors are a serious problem. Below is a long answer. For people who do not want to get through this, I will summarize.

  • Leading Microsoft researchers in the correctness of the program on Spe # and projects with code contracts consider a problem that deserves attention.
  • Dr. Bertrand Meyer and the ISE software development team who developed and supported the Eiffel programming language, also believe this is a noteworthy issue.
  • In my own commercial experience developing common software, I often saw null-referenced errors that I would like to solve the problem in my own products and practices.

For many years, Microsoft has invested in research aimed at improving software quality. One of their efforts was the Spe # project. One of the most exciting events, in my opinion, with the .NET 4.0 base is the introduction of Microsoft supply contracts, which is the result of earlier work done by the Spe # research group.

Regarding your remark, "the vast majority of errors in the code are null reference exceptions," I believe that this is the identifier of the "vast majority" that will cause some controversy. The phrase "The vast majority" suggests that perhaps 70-90% of errors have an exception with a null reference as the main reason. For me it is too high. I prefer to quote Microsoft SpeC # research results. SpeC # programming system in its article: A Review, Mike Barnett, C. Rustan M. Leino, and Wolfram Schulte. In CASSIS 2004 LNCS vol. 3362, Springer, 2004, they wrote

1.0 Non-empty types Many errors in modern programs manifest themselves as zero dereferencing errors, suggesting the importance of programming a language that distinguishes between expressions that can evaluate to null and those that are not necessary (for some experimental proofs, see [24, 22]). In fact, we would like to eradicate all dereferencing errors.

This is a likely source for people at Microsoft who are familiar with this study. This article is available on Spe # website.

I copied the links 22 and 24 below and included ISBN for your convenience.

  • Manuel Fahndrich and C. Rustan M. Leino. Declaring and checking non-empty types in an object-oriented language. In the proceedings of the 2003 ACM Conference on Object Oriented Programming, Systems, Languages, and Applications, OOPSLA 2003, Volume 38, Number 11 in SIGPLAN Notifications, pp. 302-312. ACM, November 2003. isbn = {1-58113-712-5},

  • Cormac Flanagan, C. Rustan M. Leino, Mark Lillybridge, Greg Nelson, James B. Sachs, and Raymie Stata. Extended static checking for Java. In the materials of ACM 2002, the SIGPLAN Conference on the Development and Implementation of the Programming Language (PLDI), volume 37, number 5 in SIGPLAN reports, pp. 234-245. ACM May 2002

I reviewed these links. The first link points to some experiments that they looked at for their own code for possible zero support defects. Not only did they find a few, but in many cases, identifying a potential null reference indicated a wider design problem.

The second link does not contain any specific evidence that null reference errors are a problem. But the authors claim that, in their experience, these zero reference errors are a significant source of software defects. The paper then explains how they are trying to eradicate these shortcomings.

I also recalled that I saw something about this in an ISE announcement of the recent release of Eiffel. They refer to this problem as “unmistakable security,” and, like many other things inspired or developed by Dr. Bertrand Meyer, they have an eloquent and educational description of the problem and ways to prevent it in their language and tools. I recommend that you read their article http://doc.eiffel.com/book/method/void-safety-background-definition-and-tools to find out more.

If you want to know more about Microsoft code contracts, a lot of articles have appeared recently. You can also check out my blog at http: SLASH SLASH codecontracts.info, which is mainly about talking about software quality using contract programming.

+28
Feb 01 '10 at 5:41
source share

In addition to the above (Null Objects, Empty Collections), there are some common methods, namely Resource Assquisition is Initialization (RAII) from C ++ and Design By Contract from Eiffel. They come down to the following:

  • Initialize variables with valid values.
  • If the variable can be null, then either check the null value, or consider it as a special case or expect the link to be thrown out (and handle it). Claims can be used to verify contract violations in development assemblies.

I saw a lot of code that looks like this:

if ((value! = null) && (value.getProperty ()! = null) & & ... && (... doSomethingUseful ())

In most cases, this is completely unnecessary, and most tests can be removed with stricter initialization and stricter definitions of contracts.

If this is a problem in your code base, then in each case you need to understand what null means:

  • If zero represents an empty collection, use an empty collection.
  • If zero represents an exceptional case, throw an exception.
  • If the null value is a randomly uninitialized value, explicitly initialize it.
  • If the null value is a legitimate value, check it out - or even better, use a NullObject that executes the null operator.

In practice, this standard of clarity at the development level is non-trivial and requires effort and self-discipline for the consistent application of the code base.

+20
Dec 22 '09 at 1:03
source share

No.

Or rather, there is nothing special to try to “prevent” NREs in C #. For the most part, NRE is just some logical mistake. You can use a firewall at the borders of the interface, checking the parameters and having a lot of code, for example

 void Foo(Something x) { if (x==null) throw new ArgumentNullException("x"); ... } 

all over the place (most of the .Net Framework does this), so when you screw up, you get a little more informative diagnostics (stack tracing is even more valuable, although NRE also provides this). But you still just end the exception.

(In addition to this: exceptions, such as NullReferenceException, ArgumentNullException, ArgumentException, ... - as a rule, should not be caught by the program, but simply means "the developer of this code, there is an error, please correct it." Refer to them as an exception " development time ", compare them with the true" runtime "exceptions that occur as a result of the runtime (for example, FileNotFound) and are intended for potential infection and processing by the program.)

But at the end of the day, you just need to encode it correctly.

Ideally, most NREs will never happen because null is a meaningless value for many types / variables, and ideally, a static type system prohibits null as a value for these specific types / variables. Then the compiler will prevent you from introducing such a random error (the exception of some classes of errors is what compilers and type systems are best suited for). This means that some languages ​​and type systems are superior.

But without these functions, you simply check your code to make sure that you have no code paths with this type of error (or perhaps use some external tools that can do additional analysis for you).

+7
Dec 22 '09 at 0:50
source share

Use Zero Object Templates here.

Make sure you want the collections to be empty if they are not filled, not null. Using an empty collection when an empty collection will be confused and often not needed.

Finally, I make my objects validated for non-empty values ​​when building where possible. Thus, I have no doubt later on whether the values ​​are null, and only need to perform null checks where necessary. For most of my fields and parameters, I can assume that the values ​​are not null based on previous statements.

+5
Dec 22 '09 at 0:22
source share

One of the most common null reference errors I've seen is strings. There will be a check:

 if(stringValue == "") {} 

But the line is really zero. It should be:

 if(string.IsNullOrEmpty(stringValue){} 

In addition, you may be overly cautious and verify that the object is not null before trying to access the elements / methods of this object.

+4
Dec 22 '09 at 0:23
source share

You can easily check for a null reference before it raises an exception, but this is usually not a real problem, so you just end up throwing an exception because the code cannot continue without any data.

Often the main problem is not that you have a null link, but you have a null link in the first place. If the link should not be null, you should not go past the point where this link is initialized without the correct link.

+4
Dec 22 '09 at 0:27
source share

One way is to use Null Value objects (aka Null Object Pattern ), where possible. There is more here

+3
Dec 22 '09 at 0:18
source share

Indeed, if your language has null values, this should happen. Errors of null reference come from errors in the application logic, therefore, if you cannot avoid all those whom you hit.

+3
Dec 22 '09 at 0:20
source share

Appropriate use of structured exception handling can help avoid such errors.

In addition, unit testing can help you ensure that your code behaves as expected, including ensuring that values ​​are not null if they should not.

+2
Dec 22 '09 at 0:20
source share

One of the easiest ways to avoid NullReferenceExceptions is to aggressively check for null references in class constructors / methods / installers and draw attention to the problem.

eg.

 public MyClass { private ISomeDependency m_dependencyThatWillBeUsedMuchLater // passing a null ref here will cause // an exception with a meaningful stack trace public MyClass(ISomeDependency dependency) { if(dependency == null) throw new ArgumentNullException("dependency"); m_dependencyThatWillBeUsedMuchLater = dependency; } // Used later by some other code, resulting in a NullRef public ISomeDependency Dep { get; private set; } } 

In the above code, if you pass null ref, you will immediately know that the calling code is incorrectly using this type. If there was no zero check, the error can be hidden in various ways.

You will notice that the .NET Framework libraries almost always fail early and often if you provide null references where this is not valid. Since the exception, clearly thrown, says: "You messed up!" and tells you why this makes finding and fixing defective code a trivial task.

I have heard complaints from some developers who say that this practice is too verbose and redundant, since the NullReferenceException is all you need, but in practice, I find this to be of great importance. This is especially important if the call stack is deep and / or the parameter is stored and its use is delayed until very late (possibly in another thread or hidden in some other way).

Would you prefer an ArgumentNullException in the input method or an unclear error in the guts? The farther away you are from the source of the error, the more difficult it is to trace it.

+1
Dec 22 '09 at 1:05
source share

Good code analysis tools can help here. Good unit tests can also help if you use tools that treat null as a possible way through your code. Try throwing this switch in your build settings, which says “handle warnings as errors” and see if you can save # warnings in your project = 0. You may find that warnings tell you a lot.

Keep in mind that this can be a good thing in which you throw an exception using a NULL reference. What for? because it may mean that the code that was supposed to execute did not. Initializing defaults is a good idea, but you must be careful not to hide the problem.

 List<Client> GetAllClients() { List<Client> returnList = new List<Client>; /* insert code to go to data base and get some data reader named rdr */ for (rdr.Read() { /* code to build Client objects and add to list */ } return returnList; } 

Okay, so that might look fine, but depending on your business rules, this might be a problem. Of course, you'll never throw a null reference, but maybe your User table should never be empty? Do you want your application to spin in place, generating support requests from users saying "it's just a blank screen", or do you want to create an exception that can be logged somewhere and quickly raise an alert? Be sure to check what you are doing, as well as "handle" the exceptions. This is one of the reasons why some of them do not want to accept zeros from our languages ​​... it makes it easier to find errors, even if it may cause some new ones.

Remember: handle exceptions, do not hide them.

0
Dec 22 '09 at 1:45
source share

You can use the Zero Object Pattern and the Special Case Template in cases where there may be a legitimate object that can replace zero.

In cases where such an object cannot be built, since it is simply impossible to implement its required operations, you can rely on empty collections, for example, in Map -Repeat queries .

Another solution is the Functional Type of Options , which is a collection with zero or one item. Thus, you will have the opportunity to skip an operation that cannot be performed.

These are options that can help you write code without any null references and any null checks.

0
Jun 10 '15 at 9:13
source share

Simple code solution

You can always create a structure that helps you catch null-reference errors earlier by marking variables, properties, and parameters as "not nullable." Here's an example conceptually modeled after using Nullable<T> :

 [System.Diagnostics.DebuggerNonUserCode] public struct NotNull<T> where T : class { private T _value; public T Value { get { if (_value == null) { throw new Exception("null value not allowed"); } return _value; } set { if (value == null) { throw new Exception("null value not allowed."); } _value = value; } } public static implicit operator T(NotNull<T> notNullValue) { return notNullValue.Value; } public static implicit operator NotNull<T>(T value) { return new NotNull<T> { Value = value }; } } 

You would be very similar to how you would use Nullable<T> , except for the purpose of achieving the exact opposite - not allowing null . Here are some examples:

 NotNull<Person> person = null; // throws exception NotNull<Person> person = new Person(); // OK NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null 

NotNull<T> implicitly dropped to and from T , so you can use it anywhere you need it. For example, you can pass a Person object to a method that takes the value NotNull<Person> :

 Person person = new Person { Name = "John" }; WriteName(person); public static void WriteName(NotNull<Person> person) { Console.WriteLine(person.Value.Name); } 

As you can see above, using nullable, you will access the base value using the Value property. In addition, you can use explicit or implicit listing, you can see an example with a return value below:

 Person person = GetPerson(); public static NotNull<Person> GetPerson() { return new Person { Name = "John" }; } 

Or you can even use it when the method simply returns T (in this case, Person ) by doing a throw. For example, the following code will simply look like the code above:

 Person person = (NotNull<Person>)GetPerson(); public static Person GetPerson() { return new Person { Name = "John" }; } 

Merge with extension

Combine NotNull<T> with the extension method, and you can cover even more situations. Here is an example of what the extension method looks like:

 [System.Diagnostics.DebuggerNonUserCode] public static class NotNullExtension { public static T NotNull<T>(this T @this) where T : class { if (@this == null) { throw new Exception("null value not allowed"); } return @this; } } 

And here is an example of how it can be used:

 var person = GetPerson().NotNull(); 

Github

For reference, I made the code above, available on GitHub, you can find it at:

https://github.com/luisperezphd/NotNull

0
Mar 08 '16 at 1:49 on
source share

Tools that can help

There are also several libraries that can help. Microsoft Code contracts have been mentioned above.

Some other tools include Resharper , which can provide you warnings while writing code, especially if you use their attribute: NotNullAttribute

There is also PostSharp , which allows you to simply use the following attributes:

 public void DoSometing([NotNull] obj) 

By doing this and making PostSharp part of your build process, obj will be checked for zero at runtime. See: PostSharp validation error

Fody code-weaving .

0
08 . '16 1:52
source share

NullReferenceException , , ex m0 = mi.GetType(). GetMethod ( "TellChildToBeQuiet" ), SportsMiniCar, mi MiniVan TellChildToBeQuiet - . , , Version 2.0.0.0, , GAC. : : `

 enter code here using System; using System.Rwflection; using System.IO; using Carlibraries; namespace LateBinding { public class program { static void Main(syring[] args) { Assembly a=null; try { a=Assembly.Load("Carlibraries"); } catch(FileNotFoundException e) { Console.Writeline(e.Message); Console.ReadLine(); return; } Type miniVan=a.GetType("Carlibraries.MiniVan"); MiniVan mi=new MiniVan(); mi.TellChildToBeQuiet("sonu",4); Console.ReadLine(); } } } 

MiniSportsCar TellChildToBeQuiet ( ChildName, int count)

-one
16 . '17 23:03
source share



All Articles