Reputation: 9403
Is there a way to create a non nullable type in C# (like DateTime or TimeSpan).?
Also is there a way (an attribute maybe) to enforce that not null arguments wouldn't be passed to methods and properties without adding
if(arg1 == null)
{
throw new ArgumentNullException("this attribute is null")
}
Upvotes: 14
Views: 9898
Reputation: 686
YES! C# 8.0 introduced non-nullable reference types: https://learn.microsoft.com/en-us/dotnet/csharp/nullable-references
string message = null;
// warning: dereference null.
Console.WriteLine($"The length of the message is {message.Length}");
var originalMessage = message;
message = "Hello, World!";
// No warning. Analysis determined "message" is not null.
Console.WriteLine($"The length of the message is {message.Length}");
// warning!
Console.WriteLine(originalMessage.Length);
This is enabled by default on new projects. If you update the .NET version of an existing project, this won't be automatically enabled, but you can enable it in Project -> Properties -> Nullable
.
Upvotes: 1
Reputation: 180
As for the second question, here is an idea inspired by Nullable<T>
.
A method with null-checked arguments would look like:
void Foo(NotNull<string> s)
{
var x = $"{s}";
var i = int.Parse(s);
}
Usage of NotNull<T>
isn't limited to method arguments. And it would be certainly nice if the language has some syntactic sugar for it in the future, e.g. Foo(string! s)
.
public struct NotNull<T> where T : class
{
private T valueField;
public NotNull(T value)
{
this.valueField = value;
this.CheckNotNull(value);
}
public T Value => this.valueField;
public static implicit operator T(NotNull<T> t)
{
return t.Value;
}
public static implicit operator NotNull<T>(T t)
{
return new NotNull<T>(t);
}
public override bool Equals(object other)
{
return this.Value.Equals(other);
}
public override int GetHashCode()
{
return this.Value.GetHashCode();
}
public override string ToString()
{
return this.Value.ToString();
}
private void CheckNotNull(T value)
{
if (value == null)
{
throw new InvalidOperationException($"Value cannot be null");
}
}
}
Upvotes: 1
Reputation: 73163
Of course you can write your own value types (enum
and struct
) which can't be null (unless made nullable).
As for the second part, you can have a generic parameter and a constraint of accepting only value types, which means argument can not be null - not very useful considering vast majority of cases we use class
.
public static void Do<T>(T arg1) where T : struct
{
//both struct and enum goes here.
}
Upvotes: 0
Reputation: 9876
In addition to the AOP solutions mentioned, Enterprise Library offers this in their validation block. http://msdn.microsoft.com/en-us/library/ff953182(v=pandp.50).aspx
Upvotes: 2
Reputation: 22496
You are right: this is a shortcoming in C# compared to C++. This is a shame, because 95% of all parameters I pass to functions are non-null pointers. In C++, you can add compiler-checked documentation indicating which pointers are ensured to point to something.
Upvotes: 4
Reputation: 1062492
The null-checking you refer to will be easier in .NET 4.0 / C# 4.0 via code-contracts, which does pretty much what you want.
Structs are already non-nullable, but don't go creating your own structs like crazy - you rarely need them (classes are far more common). There is no real concept of a "non-nullable class"; people have proposed syntax changes like:
void Foo(string! arg1) {...}
which would have the compiler do the non-null check on arg1
- but in reality, code-contracts does this and more. There are some things you can do in PostSharp, but it probably isn't worth the hastle.
One other thought on a non-nullable class (and one of the reasons they aren't implemented); what would default(T)
be for a non-nullable class? ;-p The spec demands that default(T)
is well defined...
Upvotes: 11
Reputation: 164281
A non-nullable type is a ValueType, in other words a struct. A struct cannot be null, so an example would be:
public struct MyStruct {}
There is no built-in way of ensuring that null is not passed as a parameter to a method (unless the type of the parameter is a ValueType). I have seen people create extension methods for doing a simpler (ie. less code) assertions on whether a parameter is null, this might be an option for you. On the other hand, the check is short to begin with; and the intent of the check is very clear. That might not be the case if you use a custom method of checking.
C# 4.0 will add better options for doing this kind of programming by contract, but is not available yet. As pointed out in another answer PostSharp is an option for doing what you want. PostSharp works by adding a post-compilation step where extra code is added.
There are some options for statically checking whether null might be passed, however. For example, ReSharper lets you decorate your own method parameters with a [NotNull] attribute, and ReSharper will issue warnings at compile time if it can determine that the parameter might be null. Of course this only warns you about (potentially) bad coding practice, it is not a runtime check and should not be used as such.
Upvotes: 6
Reputation: 115691
DateTime
and TimeSpan
are not-nullable since they are struct
s rather than class
es.
As for your second question, there is no standard way you can do this in C#. You can do this using PostSharp, which is an AOP framework, or with Spec#, which is a whole new language (an extension of C#) which allows for some of desired behavior.
Upvotes: 16
Reputation: 136593
Structs (value type) variables will never be null - that explains your DateTime case. So if your method params are C# structs, you can be sure they will never be null.
However if your method params are reference types, they can be null. I dont think you can do away with the null check as you've shown above in that case.
Upvotes: 1