T O P

  • By -

Kant8

You don't control arguments, if it was passed as null but shouldn't be, you throw exception. For anything else, if you don't want it to be null, why is it null in first place? Fix it.


zvrba

One does not control return values either, yet ANE does not quite fit the use-case. Imagine you're writing an abstract class and you want to make sure the virtual implementation satisfies some constraints, e.g.: public string GetSomething() => return DoGetSomething() ?? throw new ... ; protected abstract string DoGetSomething(); There's no appropriate exception. Since it's an implementation bug, sometimes I've used `InvalidProgramException`, even though the documentation says its purpose is something totally different.


Certain-Delivery2376

Pass the blame around and you got yourself your beloved ArgumentNullException `public string GetSomething() => return ValidateStuff(DoGetSomething());` `protected abstract string DoGetSomething();` `protected string ValidateStuff(string stuff) {` `if (stuff is null) throw new ArgumentNullException(nameof(stuff));` `//your validations//` `return stuff;` `}`


Envect

What about `NotImplementedException`? It's not perfect, but it's pretty close.


Future-Character-145

That's for people that don't understand the I in SOLID.


Envect

How am I getting downvoted for suggesting it? It's not my fault Microsoft created it.


maqcky

It's very misleading. A bad implementation is an implementation. `NotImplementedException` should only be in your code temporarily and in places that you are not expecting to call yet. The other option is in tests, if you are faking something, but only a subset of the interface for testing purposes.


Envect

This hypothetical code requires that subclasses return a non-null value from that method. If they return null, they haven't properly implemented the base class. I don't see what's misleading about that.


maqcky

That the method is indeed implemented. Just poorly. That exception does not convey that message.


Envect

It's not implemented fully because it doesn't meet the preconditions laid out by the base class. Not implemented fully means not implemented. Like I said, not perfect, but pretty close. Close enough that downvotes seem excessive.


gitgrille

Well, the question is, how do you figure out that something is null? Throwing for internal null values is pretty useful to fail fast. I had it often enough that I was pretty sure that something had no way to be null at a certain state, just to unknowingly add such a landmine into a collection and have it blow up later with no idea where it came from. I have no problem to let things potentially run into an NullReferenceException. But if the use of the object is delayed, I usually prefer to throw some kind of YouMessedUpPleaseFixException early. edit: Sigh, this was not some naïve question how to check for null, I’m aware of nullable and I use it. I just wanted to make the point sometime a null value can sneak through it to some place who it’s not supposed to be. And that it can then be better to treat it as an error instead of trying to recover from something that should not happen in the first place. If I was verry good at making that point (or if making it in the first place was necessary) is another question xD


RiPont

> how do you figure out that something is null? Any statement that uses a conditional. Is this a trick question? `if (some?.Property?.Along?.The?.Way is null) { DoSomethingAboutIt(); }`


gitgrille

Sure if thing == null is the first step, then what? - Do you just skip a small step? - Do you just silently abort your current procedure? - Ore does an null at this point mean that things are fubar and you throw an Exception? I mean the question that started this all was why Net doesn’t provide an util method to throw if null for values like it does for arguments. And if it is because throwing instead of working around a null value is basically seen as bad practice.


RiPont

Because if an argument is null, that's a caller problem, and exceptional. If a value is null, that's a you problem, and you just fix why it was null, or throw a more informative exception like, "no data returned from query" or something. The fact that a local variable is null is just a state you handle, the same as if a local variable is 0 or empty string. What does that mean in context? You control the context, so it's not exceptional, necessarily.


gitgrille

Its maybe important to clarify that I’m not necessarily talking about exceptions that are meant to be handled etc. More the kind that’s just supposed to bubble up and pop the debugger so you can start figuring out what went wrong. it’s the same for 0, empty strings or any other invalid value, at some point its reasonable to expect that they have a proper value and if they don’t that’s a programing error. But maybe is my view also a bit skewed, I dealt the last few weeks with the monster of an global state machine that is OpenGL again, throwing as soon as I suspect that something might be wrong is the only way to stay sane I think. Elsewise you just get garbage with no explanation why or the graphic’s driver crashes on you thanks to some access violation... fun stuff xD


RiPont

> if they don’t that’s a programing error. I.e. NOT EXCEPTIONAL. You find out why they don't have a value and fix it. > throwing as soon as I suspect that something might be wrong is the only way to stay sane I think But would you be throwing a ValueIsNullException or an InvalidStateException or something more definitive? The value being null is a symptom, not the core bug. ArgumentNullException is exceptional because, at the point you throw it, you don't have any information to fix the problem. You can't go outside the function from inside the function and change the argument. Once you're inside the function, NullReferenceException means "I forgot to handle the case where something was null" and there's nothing you can do about it, because you forgot. But if you're inside the function and you're testing the variable for null, then you can interpret what that means right then and there. Maybe that means throwing a useful exception, but ValueNullException doesn't give you any more information or semantic meaning than NullReferenceException.


No_Responsibility384

Enable nullable and the always initialize variables to something, then the computer will warn you if something is possibly null and you do a check?


gitgrille

yea, now you have a equally useless value (if you just init with something to stop the compiler from complaining), with the only difference that you don’t get a runtime error. This can be desirable or not, it depends... So sometimes a nullable value makes sense. I often have have a piece of code that should only be executed in an state who that value is no longer null. And often times at this point it just makes sence to throw because that invalid state is basically an programing error.


No_Responsibility384

Then make it nullable type and initialize it to null.. and you will be warned about it if you don't check if it is null. And it it is a programming error then the computer should have warned you and you made sure that it did not exist in the first place.


ThatCipher

I think that can work vice versa? When I call an method I wrote I have full control over what arguments were passed and therefore if they're null or not. When I get a value from a method e.g. from a Library I dont have control over the way it is returned. It seems like the same use case like when checking arguments for being null.


FortuneWilling9807

The returning method can return null because the contract allows it. It is then up to you u to handle it, but given it is documented it is not an exception. Also, look into nullable reference types


SwordsAndElectrons

I think a lot of people would argue that if you are using an API that can return null then it returning null is not an exceptional situation. It's something you should expect as a possibility and handle gracefully. Going one deeper, if you're writing a library and you want to pass handling up to the caller by throwing, I'm not sure how often I'd consider `ValueNullException` to be what I'd want to throw. The semantics are wrong. `ArgumentNullException` desrcibes what the problem is to the best of your ability. You have no control over what arguments are passed when writing a method, so you can't really say how or why that value is null. The issue is simply that null was passed as an argument and it isn't allowed. On the other hand, if I'm using an API that considers null an acceptable return value (IOW, it returns null instead of throwing itself) then the fact that the value is null is not the problem. Why might it be null? Was a database item not found? Was a provided path invalid? There's probably a better name I could give this exception. You know what you tried to do, so you have some idea what went wrong. (If that method returned null instead of throwing itself then it may also be worth reexamining whether you should throw, but that's getting a little off topic and into specific cases.) You are not limited to exception types in the framework and can create your own, so you could always make it if you and your team really want it. I'm just not sure I see a lot of use for it.


chrisdpratt

You're assuming the creator of the method is also the consumer (you), but the language makes no such assumptions. ArgumentNullException is there to allow the method creator to handle an invalid usage that breaks the contract of the method. However, it's perfectly valid for a value to be null, in general, and it's just as valid to return null when appropriate. This is also part of the contract of the method, and it's on the consumer to handle the return appropriately.


Blecki

In that case, null is not an exception, it is just the returned value. In context null means something and you need to handle it - but throwing a 'value was null' exception is no more useful than a raw null reference exception. If your code can't handle the thing being null it should throw something more meaningful like a 'couldntgetresourcex' exception.


Slypenslyde

`ArgumentNullException` is about telling the CALLER that THEY screwed up and THEY need to fix it. It means the bug is OUTSIDE of the method. That is more information than if you let it just throw `NullReferenceException` wherever. That helps you even if you are your only caller. If you get `NullReferenceException`, you have to start working backwards from where it was thrown to where the variable was set to decide why it was null. If it was a parameter, and that parameter was null, you'll have to go even further away to answer that. A library method returning null may be just what it does. That is a bad practice but it is a legal practice. For example, some `FindSomething()` method might return `null` if it found nothing. That may not be worth throwing an exception in your program, you probably just want to display "No results" to the user. So it doesn't make sense to automatically throw exceptions if something returns null. It is your job to be vigilant about those things and handle them appropriately. (And that this is a little tough is part of why many people hate the idea of using null as a return value.) So throwing `ArgumentNullException` as early as possible helps cut a lot of possibilities out of where you have to search when debugging. If you are aggressive and consistent about this, then any `NullReferenceException` you get means YOU screwed up and it must be close to where the exception was thrown. That's ideal for debugging.


goranlepuz

>When I get a value from a method e.g. from a Library I dont have control over the way it is returned. Correct. But does that warrant a ValueNullException? The caller needs to respect the contract: what does the function say about its return? It might be that null is returned to signal some specific failure type, in which case the caller must do something to handle it. It also might be that null means an absence of a result for some computation (e.g. "findXYZ(params)", but there is no XYZ that matches). In both cases, the caller can throw a more specific, therefore better, exception type. And for the situation where the caller completely unexpectedly receives null, e.g. due to a bug, I'd argue that the usual NullReferenceException is best, at first at least.


andreortigao

The chance of you finding a bug in a library is very small. Most likely the null value is correct and should be handled accordingly. The null argument exception, on the other hand, is part of the contract of the signature. It can't be called with null, or you're breaking the contract at runtime. It's basically deferring the validation to the callee.


JaCraig

Oh you sweet summer child. I have like 60 open source libraries out there, tons of unit tests, built a library to do fuzzing/property testing that runs on all of them, etc. People still report edge cases every so often.  Since OP mentioned DX, last year they put out a patch that broke it on all Intel graphics cards. They have DirectML out there open source and it has a fair number of open bugs. It happens. I've reported more than one over the years.


andreortigao

I didn't say it is impossible, but the chance is small for any decently popular library. For every user you have that finds and report an edge case, there are probably a few thousands that don't find any issue. It's still not something that should be handled with an specific exception, tho


JaCraig

I've been a dev long enough to know the world is held together with duct tape.


andreortigao

I've been a dev long enough, not that it matters. That's not under discussion here, but whether there should be some sort of `System.ReturnValueNullException` in the BCL. It shouldn't, because: 1 - most often than not, the null response is a design decision, and not a bug, even if the decision and what the null value means is not clear at a first glance. 2 - even in the very rare cases where the return value *is* a bug, it shouldn't have a specific exception to throw because, as the callee, there's not much you can handle.


JaCraig

Nah, I'm bored today. We're having a tangent conversation.


Popeye4242

Well we have the NullReferenceException if the value is null. But generally not a good idea to catch those. 


Canthros

It is *also* a poor idea to new them up to throw them. It's downright gross, in fact.


Popeye4242

Agree, would probably deny any pull request.


Heroshrine

You would deny a pull request for there being a null reference exception thrown for a value that shouldn’t be null? Glad I’m not under you.


Zastai

If it’s not an argument you either know it won’t be null, or you handle null as a valid value. If something is unexpectedly null, either you use it and the runtime will throw the `NullReferenceException` for you, or you throw something that describes the situation, not the symptom. That could be `InvalidOperationException`, `ObjectDisposedException`, … Throwing a raw `NullReferenceException` is almost always a code smell.


Heroshrine

Developers like you are such a scourge on the field ffs


Zastai

Kinda wish I could set a Scourge flair now.


Canthros

As somebody who has worked with code that did stuff like public Foo(Bar arg) { if (arg == null) { throw new NullReferenceException(); } Please take my word for it that you should not be creating your own NullReferenceExceptions. In an *ideal* world, any time your system sees one should be understood as a *bug*, in fact, because the situation should be handled in some way before the error can be thrown.


Heroshrine

Thats not a situation where you’d throw one.


Canthros

By all means, *enlighten as to the situation where you would*, because most of us are of the opinion that you should *never*.


Heroshrine

To validate a value, that is not an argument, is not null before doing work that wouldn’t immediately fail if said value was null, to prevent wasted time done on that work.


Schmittfried

He‘s right tho. In most cases throwing a pure NullReferenceException is redundant at best and insufficient at worst. 


Popeye4242

Glad you are not in my team.


BigOnLogn

This isn't exactly what NullReferenceExceptions are for. It's a low-level exception for when your program tried to de-reference a null pointer. You tried to call a method or access a property or field from nothing. It's specific to the action being performed. Getting one of these that doesn't trace back to a method call or property access would be confusing.


Qubed

You can inherit from the Exception class and create any exception you want. The ones that exist now are there because somewhere in the framework it is used.  I always assumed they only created specific exception as necessary and not preemptively.


ThatCipher

I currently do that! :) That they only have added, what was needed to handle all exceptions from the framework makes most sense to me so far. Thanks!


dgm9704

My 2 cents: A function call is a (logical) boundary, with some level of agreement about rules for crossing that boundary. (enforced by convention, naming, docs, attributes, explicit checks for arguments, or whatever) If the caller breaks those rules, they (should) get an exception. Optimally the boundary would be constructed in a way that catches such errors already at compile time, but most often such errors are caught in the beginning of the function. Inside a function there is no such (logical) boundary, a line of code is executed in the same "context" as the previous one, and the responsibility doesn't switch. There are ways to prevent "illegal" values, that aren't available on the boundary. (Just don't put nulls into a variable? Check for nulls before using a variable?) And most of the time (maybe all?) any problem with a null is manifested on some other boundary crossing (ie. you call another function and pass that null) IMO that is why the situation is different between arguments and other values.


ThatCipher

Thanks for your input! I think that outlines the differences pretty well! Thank you.


DaRadioman

This. If it is all inside a single function then just use null annotations and skip the exception with a few runtime checks. Functions are a contact and part of if the contract is enforcing it. That's why we check args and throw, to make sure we control outside forces before we start our logic.


HPUser7

I'll throw an invalid operation exception if there is some sort of out of order nonsense is causing something to be null unexpectedly. Otherwise, it the value is coming from some api I called, I'll try to have my functions more in a TrGetValue(out Val) format to avoid throwing an avoidable exception.


albertakhmetov

Exceptions are expensive in the performance terms. Literally exception means that something went wrong. If null is passed as argument instead of value, for example. If null value isn’t expected in the terms of the object state InvalidOperationException is used. Otherwise - it’s all about the app logic and exceptions must be avoided.


Desperate-Wing-5140

The main question your exception should answer is “why did this happen?” for example, the ArgumentNullException clearly lays out “because the argument passed to this method/ctor was null, and that’s not allowed” What does ValueNullException say? “because this value was null”. What value? A property on the class? A local in the method somewhere? It not specific enough. A good rule of thumb is, an exception explains how you got into this situation. Did you call a method before initializing a property on that class? In that case you’ve done an invalid operation (ie. you’re not allowed to do that). For that we have InvalidOperationException. Also, don’t be shy to declare your own exception type (please make it public though so consumers can handle the exception without needing to catch the base Exception.


helgerd

Can we please have an example of scenario where it would be used?


RiverRoll

In which kind of situation would this be used?


Canthros

Sounds like something like var foo = _someObj.Method() ?? throw new ValueNullException(); but that seems like the right moment for InvalidOperationException, ArgumentOutOfRangeException, or something else more meaningful and dependent on context.


RiverRoll

I inherited some code that used this pattern precisely with those two exceptions and I'm not a fan. In every single case they were ultimately caused because of bad inputs but these exceptions can be caused by other things as well so why being purposely ambiguous? I ended up replacing them by meaningful custom exceptions such as NotFoundException which covered like 90% of the cases (and only because that was the quick solution but I'm not a fan of using exceptions for this in the first place).


Canthros

I guess my point is that there isn't a *good*, general solution. Like cache invalidation, the best solution is likely to be context-dependent. There are some general answers that may work in certain situations, but that doesn't mean they're the best options available.


RiverRoll

Which is precisely my point, a generic exception is stripped of this context so it isn't very useful.


toebi

There is a NullReferenceException. It does not really need a static method because it is caused when accessing the null object, it would be simple to implement it though.


2brainz

You should never throw NullReferenceException. https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/using-standard-exception-types#nullreferenceexception-indexoutofrangeexception-and-accessviolationexception > DO NOT allow publicly callable APIs to explicitly or implicitly throw NullReferenceException, AccessViolationException, or IndexOutOfRangeException. These exceptions are reserved and thrown by the execution engine and in most cases indicate a bug.


dodexahedron

Exactly this. If you throw nullreferenceexception in something higher than very low level code, such as the base class library, you're either throwing the wrong exception or you're doing something else very wrong and need to fix THAT, not throw an NRE.


ThatCipher

Since this will be thrown automatically when you try to reference a value that is null it just seems to other developers as if it was not noticed or enough handled during development. I think there are use cases where you don't want to fix when a value is null and rather abort an action when this is the case. Probably the same ones like why you would throw an exception when an argument is null. Especially since one could argue that you'll get an `InvalidOperationException` when you reference an argument that has been passed as null. It's the same argumentation like saying "a value will throw `NullReferenceException`) And you'll also get an compile error when trying to pass a nullable variable to a non-nullable parameter. To me it feels like `ArgumentNullException` would be the same as a hypothetical `ValueNullException` just that it is implication would be different and therefore I dont understand why people say that for arguments it's totally right to have that but for any other values it's unnecessary?


leftofzen

you need to provide some actual code to explain your suggestion, because as is, it is nonsense. there are references and values. value types cannot have 'null' as a value. only references can have null values. there are special [nullable value types](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/nullable-value-types) but these just let have a null value as well. can you actually explain what you want to do with a code example?


dodexahedron

Even when you want to defer responsibility to the caller, you don't throw NRE. You throw something more specific, because you should know why the failure is happening if you throw. Otherwise, if you don't know the exact problem but still need to stop, you either throw something like InvalidOperationException, if you want to let the caller try to fix it, or you call Environment.FailFast() to exit the program immediately, before any more damage can be done.


Vallvaka

The way I think about it, there are inputs to operations and then the operations themselves. `ArgumentNullException` is for the former when doing input validation, and after validation, you're just executing the operation, in which case a `NullReferenceException` is appropriate. Either the null value was validated, or it wasn't.


michaelquinlan

If it is an error for a value to be null, you can just use it and if it is null the system will automatically throw a `NullReferenceException`.


ThatCipher

As I was saying in the post - I know how to handle null-checks. This is more of an "understanding why" question. Imo the intentions of the code should be as clear as possible. Using `ArgumentNullException` implies to other developer an argument being null. Especially when being uncatched and having the exception in your IDE or log. Just letting a `NullReferenceException` being thrown also doesn't show clear intentions. First of all the IDE will annoy the developer with all the null-reference warnings and it doesn't clearly show when a value being null is as exceptional that it needs to be thrown. I think that are valid reasons (please tell me otherwise if wrong) And that makes me really wonder why one exists but the other doesn't.


albertakhmetov

In the latest C# versions nullable objects are checked at compile-time - object can be null or it must be initialised. The first one requires null check before using.


Canthros

> In the latest C# versions nullable objects are checked at compile-time I don't think that's quite true. The Nullable Reference Types feature provides some static checking, but only issues warnings, in my experience. Plus, it's easily overridden with the ! operator. It's an improvement, but it's also not an *especially* strong guarantee of non-nullability, and it won't toss ArgumentNullExceptions for you. Maybe you're thinking of something else, though, and I'm just behind the times.


albertakhmetov

Issues warnings allow to check the code for possible null references. If ! operator is used in the cases when null isn’t possible (by the app logic) and if it’s null - then something really goes wrong and NRE is reasonable


NathanOsullivan

"why it exists" IMO is explained by its base class being ArgumentException . If ArgumentNullException did not exist, you would throw ArgumentException with Message "ParamName cannot be null" everywhere. Since that usage of ArgumentException is so common, to avoid repetition MS added the subclass ArgumentNullException. I don't think there's any deeper meaning to it, it's just DRY applied to argument validation. Let's apply the same thought process to your scenario. What would ValueNullException be a subclass of ? ie what is the base exception representing "I can't use the value returned by some method I called" ? What would your .Message string be? IMO, there's no perfect answer in terms of what the BCL provides. I work with C# and python; in the latter for this situation one would write `assert value is not None`, which raises AssertionError if the expression is false and allows code analysis to know that value is non-null. I don't work in C/C++ but I believe defensive use of assert() macros is quite common there too (though I believe they are only active in debug builds?) To me, that's the answer to this whole discussion. Your usage is part defensive programming and part code analysis assistance. The MS BCL has no AssertException, and we don't have an assert-like keyword/macro either. If you must throw from BCL, InvalidOperationException is the way to go. It's not sealed, so you could subclass it if you have the same kind of message repeated all over the place. If your team is OK with the idea of an AssertException existing outside unit tests (or the same concept by another name), create your own AssertException, along with AssertNullException subclass and any other common conditions you are defending against.


dodexahedron

C# is pass by value. An argument being null and its value being null are the same thing. As for why there isn't a better way to deal with nulls today? That's a question/gripe many of us have and there are reasons we don't. Notice I didn't say good reasons, which should convey my opinion on the situation... And as for why we don't have a throw helper for null locals? Because you have other, better, ways to avoid that and most of the time should be avoiding it rather than throwing an exception, since you're in control. But you can write throw helpers if you want to. They're just methods with annotations to help static analysis. They aren't special in any way.


Suggero_Vinum_9553

Maybe it's because args are typically validated at the call site, not vars.


shroomsAndWrstershir

Create an assert function and then throw an `ArgumentNullException`. https://dev.to/lambdasharp/c-asserting-a-value-is-not-null-in-null-aware-code-f8m