Mark parameters as NOT nullable in C#/.NET?

C#.NetParametersNull

C# 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNeil C. ObremskiView Question on Stackoverflow
Solution 1 - C#Jon SkeetView Answer on Stackoverflow
Solution 2 - C#GregView Answer on Stackoverflow
Solution 3 - C#rsennaView Answer on Stackoverflow
Solution 4 - C#NotMeView Answer on Stackoverflow
Solution 5 - C#Jeff GrizzleView Answer on Stackoverflow
Solution 6 - C#Martin CapodiciView Answer on Stackoverflow