Mark parameters as NOT nullable in C#/.NET?
C#.NetParametersNullC# Problem Overview
Is there a simple attribute or data contract that I can assign to a function parameter that prevents null
from being passed in C#/.NET? Ideally this would also check at compile time to make sure the literal null
isn't being used anywhere for it and at run-time throw ArgumentNullException
.
Currently I write something like ...
if (null == arg)
throw new ArgumentNullException("arg");
... for every argument that I expect to not be null
.
On the same note, is there an opposite to Nullable<>
whereby the following would fail:
NonNullable<string> s = null; // throw some kind of exception
C# Solutions
Solution 1 - C#
There's nothing available at compile-time, unfortunately.
I have a bit of a hacky solution which I posted on my blog recently, which uses a new struct and conversions.
In .NET 4.0 with the Code Contracts stuff, life will be a lot nicer. It would still be quite nice to have actual language syntax and support around non-nullability, but the code contracts will help a lot.
I also have an extension method in MiscUtil called ThrowIfNull which makes it a bit simpler.
One final point - any reason for using "if (null == arg)
" instead of "if (arg == null)
"? I find the latter easier to read, and the problem the former solves in C doesn't apply to C#.
Solution 2 - C#
I know I'm incredibly late to this question, but I feel the answer will become relevant as the latest major iteration of C# comes closer to release, then released. In C# 8.0 a major change will occur, C# will assume all types are considered not null.
According to Mads Torgersen:
> The problem is that null references are so useful. In C#, they are the > default value of every reference type. What else would the default > value be? What other value would a variable have, until you can decide > what else to assign to it? What other value could we pave a freshly > allocated array of references over with, until you get around to > filling it in? > > Also, sometimes null is a sensible value in and of itself. Sometimes > you want to represent the fact that, say, a field doesn’t have a > value. That it’s ok to pass “nothing” for a parameter. The emphasis is > on sometimes, though. And herein lies another part of the problem: > Languages like C# don’t let you express whether a null right here is a > good idea or not. >
So the resolution outlined by Mads, is:
> 1. We believe that it is more common to want a reference not to be null. Nullable reference types > would be the rarer kind (though we don’t have good data to tell us by > how much), so they are the ones that should require a new annotation. > > 2. The language already has a notion of – and a syntax for – nullable value types. The analogy between the two would make the language > addition conceptually easier, and linguistically simpler. > > 3. It seems right that you shouldn’t burden yourself or your consumer with cumbersome null values unless you’ve actively decided that you > want them. Nulls, not the absence of them, should be the thing that > you explicitly have to opt in to.
An example of the desired feature:
public class Person
{
public string Name { get; set; } // Not Null
public string? Address { get; set; } // May be Null
}
The preview is available for Visual Studio 2017, 15.5.4+ preview.
Solution 3 - C#
I know this is a VERY old question, but this one was missing here:
If you use ReSharper/Rider you may use the Annotated Framework.
Edit: I just got a random -1 for this answer. That's fine. Just be aware it is still valid, even though it's not the recommended approach for C#8.0+ projects anymore (to understand why, see Greg's answer).
Solution 4 - C#
Check out the validators in the enterprise library. You can do something like :
private MyType _someVariable = TenantType.None;
[NotNullValidator(MessageTemplate = "Some Variable can not be empty")]
public MyType SomeVariable {
get {
return _someVariable;
}
set {
_someVariable = value;
}
}
Then in your code when you want to validate it:
Microsoft.Practices.EnterpriseLibrary.Validation.Validator myValidator = ValidationFactory.CreateValidator<MyClass>();
ValidationResults vrInfo = InternalValidator.Validate(myObject);
Solution 5 - C#
not the prettiest but:
public static bool ContainsNullParameters(object[] methodParams)
{
return (from o in methodParams where o == null).Count() > 0;
}
you could get more creative in the ContainsNullParameters method too:
public static bool ContainsNullParameters(Dictionary<string, object> methodParams, out ArgumentNullException containsNullParameters)
{
var nullParams = from o in methodParams
where o.Value == null
select o;
bool paramsNull = nullParams.Count() > 0;
if (paramsNull)
{
StringBuilder sb = new StringBuilder();
foreach (var param in nullParams)
sb.Append(param.Key + " is null. ");
containsNullParameters = new ArgumentNullException(sb.ToString());
}
else
containsNullParameters = null;
return paramsNull;
}
of course you could use an interceptor or reflection but these are easy to follow/use with little overhead
Solution 6 - C#
Ok this reply is a bit late, but here is how I am solving it:
public static string Default(this string x)
{
return x ?? "";
}
Use this exension method then you can treat null and empty string as the same thing.
E.g.
if (model.Day.Default() == "")
{
//.. Do something to handle no Day ..
}
Not ideal I know as you have to remember to call default everywhere but it is one solution.