avoiding null reference exceptions

后端 未结 15 992
天命终不由人
天命终不由人 2020-11-28 08:50

Apparently the vast majority of errors in code are null reference exceptions. Are there any general techniques to avoid encountering null reference errors?

Unless I

相关标签:
15条回答
  • 2020-11-28 09:29

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

    Also, unit testing can help you make sure your code behaves as expected, including ensuring that values are not null when they're not supposed to be.

    0 讨论(0)
  • 2020-11-28 09:30

    You can use Null Object pattern and Special Case pattern in cases when there can be a legitimate object which can substitute null.

    In cases when such object cannot be constructed, because simply there is no way to implement its mandatory operations, you can rely on empty collections, such as in Map-Reduce Queries.

    Another solution is the Option functional type, which is the collection with zero or one elements. In that way, you will have the opportunity to skip the operation that cannot be performed.

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

    0 讨论(0)
  • 2020-11-28 09:32

    You don't.

    Or rather, there's nothing special to do to try to 'prevent' NREs in C#. For the most part an NRE is just some type of logic error. You can firewall these off at interface boundaries by checking parameters and having lots of code like

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

    all over the place (much of the .Net Framework does this), so that when you do screw up, you get a slightly more informative diagnostic (the stack trace is even more valuable, though, and an NRE provides that too). But you still just end up with an exception.

    (Aside: Exceptions like these - NullReferenceException, ArgumentNullException, ArgumentException, ... - typically should not be caught by the program, but rather just means "developer of this code, there is a bug, please fix it". I refer to these as a 'design time' exceptions; contrast these with true 'run time' exceptions that happen as a result of the run time environment (e.g. FileNotFound) and are intended to potentially be caught and handled by the program.)

    But at the end of the day, you just have to code it right.

    Ideally the majority of NREs would never happen because 'null' is a nonsensical value for many types/variables, and ideally the static type system would disallow 'null' as a value for those particular types/variables. Then the compiler would prevent you from introducing this type of accidental error (ruling out certain classes of errors are what compilers and type systems are best at). This is where certain languages and type systems excel.

    But without those features, you just test your code to ensure you don't have code paths with this type of error (or possibly use some outside tools that can do extra analysis for you).

    0 讨论(0)
  • 2020-11-28 09:34

    Plain Code Solution

    You could always create a struct that helps catch null reference errors earlier by marking variables, properties, and parameters as "not nullable". Here's an example conceptually modeled after the way Nullable<T> works:

    [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 use very similar to the same way you would use Nullable<T>, except with the goal of accomplishing exactly the opposite - to not allow 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> is implicitly casted to and from T so you can use it just about anywhere you need it. For example you can pass a Person object to a method that takes a 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 as with nullable you would access the underlying value through the Value property. Alternatively, you can use explicit or implicit cast, you can see an example with the 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 just returns T (in this case Person) by doing a cast. For example the following code would just just like the code above:

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

    Combine with Extension

    Combine NotNull<T> with an extension method and you can cover even more situations. Here is an example of what the extension method can look 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 could be used:

    var person = GetPerson().NotNull();
    

    GitHub

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

    https://github.com/luisperezphd/NotNull

    0 讨论(0)
  • 2020-11-28 09:35

    NullReferenceException can be shown when a method is not found in the assembly,for ex m0=mi.GetType().GetMethod("TellChildToBeQuiet") where the assembly is SportsMiniCar,mi is the instance of MiniVan and TellChildToBeQuiet is a method in the assembly. We can avoid this by seeing that this assembly Version 2.0.0.0 containing the above method is placed in the GAC. example:Invoking methods with parameters:`

    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();
           }
       }
       }
    

    Remember updating MiniSportsCar Assembly with TellChildToBeQuiet(string ChildName,int count)

    0 讨论(0)
  • 2020-11-28 09:37

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

    My top recommendation for people who care about software quality, and are also using the.net programming platform, is to install and use Microsoft code contracts ( http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx ). It includes capabilities to do run-time checking and static verification. The essential capability to build these contracts into your code is being included in the 4.0 version of the.net framework. If you are interested in code quality, and it sounds like you are, you may really enjoy using Microsoft code contracts.

    With Microsoft code contracts, you can guard 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 have recommended you do something like this

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

    Now I recommend

    Contract.Requires(customer != null);
    

    You can then enable the run-time checking system which will catch these defects as early as possible, leading you towards diagnosis and correction of the defective code. But don't let me give you the impression that code contracts are simply a fancy way to replace argument null exceptions. They are much more powerful than that. With Microsoft code contracts, you can also run the static checker, and ask it to investigate possible sites in your code where null reference exceptions might occur. The static checker requires a bit more experience to use easily. I would not recommend it first for beginners. But feel free to try it out and see for yourself.

    RESEARCH ON THE PREVALENCE OF NULL REFERENCE ERRORS

    There has been some debate in this thread on whether null reference errors are a significant problem. A long-winded answer is below. For people who don't want to wade through that, I will summarize.

    • Microsoft's leading researchers in program correctness on the Spec# and code contracts projects believe it is a problem worth addressing.
    • Dr. Bertrand Meyer and the team of software engineers at ISE, who developed and support the Eiffel programming language, also believe it is a problem worth addressing.
    • In my own commercial experience developing ordinary software, I have seen null reference errors often enough, that I would like to address the problem in my own products and practices.

    For years, Microsoft has invested in research designed to improve software quality. One of their efforts was the Spec# project. One of the most exciting developments in my opinion with the.net 4.0 framework, is the introduction of Microsoft code contracts, which is an outgrowth of the earlier work done by the Spec# research team.

    Regarding your remark "the vast majority of errors in code are null reference exceptions", I believe it is the qualifier "the vast majority" that will cause some disagreements. The phrase "Vast majority" suggests that perhaps 70-90% of faults have a null reference exception as the root cause. This seems far too high to me. I prefer to quote from the research of the Microsoft Spec#. In their article The Spec# programming system: An overview, by Mike Barnett, K. Rustan M. Leino, and Wolfram Schulte. In CASSIS 2004, LNCS vol. 3362, Springer, 2004, they wrote

    1.0 Non-Null Types Many errors in modern programs manifest themselves as null-dereference errors, suggesting the importance of a programming language providing the ability to discriminate between expressions that may evaluate to null and those that are sure not to (for some experimental evidence, see [24, 22]). In fact, we would like to eradicate all null dereference errors.

    This is a likely source for people at Microsoft who are familiar with this research. This article is available at the Spec# site.

    I've copied references 22 and 24 below, and included the ISBN for your convenience.

    • Manuel Fahndrich and K. Rustan M. Leino. Declaring and checking non-null types in an object-oriented language. In Proceedings of the 2003 ACM Conference on Object-Oriented Programming, Systems, Languages, and Applications, OOPSLA 2003, volume 38, number 11 in SIGPLAN Notices, pages 302–312. ACM, November 2003. isbn = {1-58113-712-5},

    • Cormac Flanagan, K. Rustan M. Leino, Mark Lillibridge, Greg Nelson, James B. Saxe, and Raymie Stata. Extended static checking for Java. In Proceedings of the 2002 ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI), volume 37, number 5 in SIGPLAN Notices, pages 234–245. ACM, May 2002.

    I reviewed these references. The first reference indicates some experiments they did reviewing their own code for possible null reference defects. Not only did they find several, but in many cases, the identification of a potential null reference indicated a broader problem with the design.

    The second reference does not provide any specific evidence for the assertion that null reference errors are problem. But the authors do state that in their experience, these null reference errors are significant source of software defects. The paper then proceeds to explain how they try to eradicate these defects.

    I also remembered seeing something about this in an announcement from ISE on a recent release of Eiffel. They refer to this issue as "void safety", and like so many things inspired or developed by Dr. Bertrand Meyer, they have an eloquent and educational description of the problem and how they go about preventing it in their language and tools. I recommend you read their article http://doc.eiffel.com/book/method/void-safety-background-definition-and-tools to learn more.

    If you want to learn more about Microsoft code contracts, there are tons of articles that have arisen recently. You can also check my blog at http: SLASH SLASH codecontracts.info which is primarily devoted to conversations about software quality through the use of programming with contracts.

    0 讨论(0)
提交回复
热议问题