Nullable primitives with Generics - c#

I'm trying to find the right thing to do with a non-null validation on a nullable boolean. I also want to be able to do the same thing with some other fields, including strings, ints, etc., so I want to use generics for the method. Here's an example of the kind of thing which can happen.
bool? myValue = null;
bool valid = ValidateNotNull(myValue);
And here's some validation code:
public bool ValidateNotNull<T>(T nullableField)
{
return nullableField != null;
}
All the answers I've found to this kind of problem suggest adding a where T : struct or where T: class to the method signature, or using default(T) in the comparison, none of which will work for a bool where false is a valid value.
Any other suggestions? The code compiles, but Resharper isn't happy about that null comparison on a value which it thinks might be a primitive, and I'd love to know what I should be doing to cheer it up.
NB: This isn't the complete code. I'm still interested in maintaining the type. This is also not the only place I've run into the problem.
NB2: Yes, it compiles and works fine. What I really want to know is whether there is a code solution for stopping Resharper from complaining, or an idiomatic way to do this which I don't know about.

The code below will validate nullable types and reference types:
public bool ValidateNotNull<T>(Nullable<T> nullableField) where T:struct
{
return nullableField.HasValue;
}
public bool ValidateNotNull<T>(T nullableField) where T:class
{
return nullableField!=null;
}

Would comparing to default work?
public bool ValidateNotNull<T>(T nullableField)
{
return Equals(nullableField, default(T));
}
Updated:
Either its a primitive, and all is well, or its not null:
public bool ValidateNotNull<T>(T nullableField)
{
return typeof(T).IsPrimitive || !Equals(nullableField, null);
}

I also want to be able to do the same thing with some other fields, including strings, ints, etc
OK, so you want a method that can be passed either a Nullable<> (which is a struct), or a reference type, and will return true iff the argument is null (note that your name appears to be the wrong way round, but there you go).
The thing is, if that's all this method has to do, then you don't need generics because you don't need type-safety. This example works and does what you want, I think:
class Program
{
static void Main(string[] args)
{
int? x = null;
int? y = 5;
string s = null;
string r = "moo";
Console.WriteLine(ValidateNotNull(x));
Console.WriteLine(ValidateNotNull(y));
Console.WriteLine(ValidateNotNull(s));
Console.WriteLine(ValidateNotNull(r));
Console.ReadLine();
}
private static bool ValidateNotNull(object o)
{
return o == null;
}
}
This outputs
True
False
True
False
which is I believe your required output.

I don't know why you thing your method doesn't work (apart from using != rather than ==), because as far as I can tell, it already works! You can compare any value of type T with null (when T is a generic type parameter). If a non-nullable value type is used for T, the result will be treated as a constant (false for == null, true for != null).
So, this should be fine.
public bool ValidateNotNull<T>(T nullableField)
{
return nullableField != null;
}
But this would also work without generics:
public bool ValidateNotNull(object nullableField)
{
return nullableField != null;
}
(Because boxing a Nullable<T> null value returns a null reference.)

You need to use
public bool ValidateNotNull<T>(T nullableField)
{
return nullableField.HasValue;
}

Related

C# 8.0 Nullable, How to indicate method checks for null [duplicate]

C# 8 introduced nullable reference types, which is a very cool feature. Now if you expect to get nullable values you have to write so-called guards:
object? value = null;
if (value is null)
{
throw new ArgumentNullException();
}
…
These can be a bit repetitive. What I am wondering is if it is possible to avoid writing this type of code for every variable, but instead have a guard-type static void function that throws exception if value is null or just returns if value is not null. Or is this too hard for compiler to infer? Especially if it's external library/package?
There are a few things you can do.
You can use [DoesNotReturnIf(...)] in your guard method, to indicate that it throws if a particular condition is true or false, for example:
public static class Ensure
{
public static void True([DoesNotReturnIf(false)] bool condition)
{
if (!condition)
{
throw new Exception("!!!");
}
}
}
Then:
public void TestMethod(object? o)
{
Ensure.True(o != null);
Console.WriteLine(o.ToString()); // No warning
}
This works because:
[DoesNotReturnIf(bool)]: Placed on a bool parameter. Code after the call is unreachable if the parameter has the specified bool value
Alternatively, you can declare a guard method like this:
public static class Ensure
{
public static void NotNull([NotNull] object? o)
{
if (o is null)
{
throw new Exception("!!!");
}
}
}
And use it like this:
public void TestMethod(object? o)
{
Ensure.NotNull(o);
Console.WriteLine(o.ToString()); // No warning
}
This works because:
[NotNull]: For outputs (ref/out parameters, return values), the output will not be null, even if the type allows it. For inputs (by-value/in parameters) the value passed is known not to be null when we return.
SharpLab with examples
Of course, the real question is why you want to do this. If you don't expect value to be null, then declare it as object?, rather than object -- that's the point of having NRTs.
There is a Guard Clauses library by Steve Ardalis that I think can help you with this situation.
You can do things like:
Guard.Against.Null (throws if input is null)
Guard.Against.NullOrEmpty (throws if string or array input is null or empty)
Guard.Against.NullOrWhiteSpace (throws if string input is null, empty or whitespace)
Guard.Against.OutOfRange (throws if integer/DateTime/enum input is outside a provided range)
Guard.Against.OutOfSQLDateRange (throws if DateTime input is outside the valid range of SQL Server DateTime values)
Guard.Against.Zero (throws if number input is zero)
In this blog post Jason Roberts made a quick explanation of the library too.
There is another Guard Class in the Microsoft.Toolkit.Diagnostics namespace but probably is not viable in all the use cases that will depend if wanna add that dependency to the project or not.

Implicit conversion from null

Looking Zoran Horvats courses at PluralSight, I'm currently implementing a Maybe type, a bit like Zoran has on its GitHub account: https://github.com/zoran-horvat/option
Generally, a Maybe is a wrapper around objects, which are either set or have a null value, avoiding null reference exceptions.
To make the code a bit shorter, I would like to use implicit conversion to map the values / nulls to their corresponding maybe types. Here an example of my code:
public void Hook(Maybe<Action<Keys>> onKeyDown, Maybe<Action<Keys>> onKeyUp)
{
_keyDownCallback = onKeyDown;
_keyUpCallback = onKeyUp;
_hookService.Hook(HookType.KeyBoardLowLevel, OnHookReceived);
}
As you can see, you can hook and pass two optional callbacks, one for keyDown and one for keyUp. I would like to pass code like this:
nativeKeyboardHookService.Hook(new Action<Keys>(OnNativeKeyDown), null);
The implicit conversion on the Maybe is currently implemented like this:
public static implicit operator Maybe<T>(T value)
{
return ToMaybe(value);
}
public static implicit operator T(Maybe<T> maybe)
{
return ToT(maybe);
}
public static Maybe<T> ToMaybe(T value)
{
if (value == null)
{
return new None<T>();
}
return new Some<T>(value);
}
public static T ToT(Maybe<T> maybe)
{
return maybe.Evaluate(
value => value,
() => default(T));
}
My question: It works fine, if I pass an actual object, mapping it to an Maybe, but if I pass NULL, I still get a NULL object, not a None object. Am I doing here something wrong or is it just not possible? I didn't find any further information regarding such a conversion.
When you pass null to Hook() that's literally all you are doing because your implicit casts aren't being invoked at all. That's because null is a valid value for a reference type, and thus no need to cast.
You can't change Maybe to a struct if you want to keep Some and None because then these would have to be structs too, which means you run into the issue that you can't inherit structs.
You can't implement a common IMaybe<T> interface either because interfaces can't be used with casts.
What I recommend is keep your behavior as is, but don't use null. Instead of passing null, pass something else like Maybe<T>.None:
class Maybe<T>
{
public static Maybe<T> None { get; } = new None<T>();
}
void Hook(..., Maybe<T>.None) { ... }
Or None<T>.Instance:
class None<T>
{
public static None<T> Instance{ get; } = new None<T>();
}
void Hook(..., None<T>.Instance) { ... }
This has the advantage of being more readable and explicit.
Your Maybe<T> is still a reference type, so null is a valid value for it:
Maybe<string> foo = null;
If you want to prevent that, you will need to make it a value type, for example something like this:
public struct Maybe<T>
{
public T Value { get; }
public bool IsEmpty => Value == null;
public Maybe(T value)
{
Value = value;
}
public static implicit operator Maybe<T>(T value)
{
return new Maybe<T>(value);
}
}
Then you can pass null to a method expecting a Maybe<T> and it will properly construct an empty Maybe<T> object.
But note that it being a value type, this now means that it is copied on every method call, so it has a different behavior to a reference type implementation.
In the end, you cannot really implement this nicely in C# simply because there is the null reference in the language. It’s only with C# 8’s nullable reference types that you will be able to prevent nulls altogether.

How to check for type in loop?

I know how to check a type of a field directly.
But how could I implement something like this
private bool checkJumpObstacle(Type type)
{
foreach (GameObject3D go in GameItems)
{
if (go is type) // won't accept 'type'
{
return true;
}
}
return false;
}
For type, I'd like to pass Car, House or Human as a parameter (those are all classes).
But this kind of code doesn't work.
EDIT: It's actually even easier using Type.IsInstanceOfType if you can't make it a generic method:
private bool CheckJumpObstacle(Type type)
{
return GameItems.Any(x =>type.IsInstanceOfType(x));
}
It sounds like you probably want Type.IsAssignableFrom
if (go != null && type.IsAssignableFrom(go.GetType());
Note that this is assuming you want inherited types to match.
Also, if at all possible, use generics instead. Aside from anything else, that would make the method really simple:
private bool CheckJumpObstacle<T>()
{
return GameItems.OfType<T>().Any();
}
Even without that, you can still use LINQ to make it easier:
private bool CheckJumpObstacle(Type type)
{
return GameItems.Any(x => x != null && type.IsAssignableFrom(x.GetType()));
}
Obviously if you don't expect any null values, you can get rid of the nullity check.

Why would you create a Try method + out vs checking for some default (i.e. NULL)

The following is C#, though the code pattern is probably relevant to any OO language.
I have two methods, MethodWithTry and MethodWithSomeReturnValue that I believe are functionally equivalent. I would like to know if one of them is the "correct" way. Is there something about one (ex. concurrency) that makes one of them a bad choice.
public void MethodWithTry()
{
int returnValue;
string someInput;
if (TryGetValueThisWay(someInput, returnValue))
{
//do something this way
}
else
{
if (TryGetValueThatWay(someInput, returnValue))
{
//do something that way
}
else
{
//do something a default way
}
}
}
public void MethodWithSomeReturnValue()
{
int? returnValue;
string someInput;
returnValue = GetValueThisWay(someInput);
if (returnValue != null)
{
//do something this way
}
else
{
returnValue = GetValueThatWay(someInput);
if (returnValue != null)
{
//do something that way
}
else
{
//do something a default way
}
}
}
The signatures for the methods being called are
public int? GetValueThisWay(string input)
public int? GetValueThatWay(string input)
private bool TryGetValueThisWay(string input, out int value)
private bool TryGetValueThatWay(string input, out int value)
EDIT -- ADDITIONAL INFO
The methods in question being called are doing finds in collections. So different names might have been
public int? GetValueFromCollectionA()
public int? GetValueFromCollectionB()
IMHO, TrySomeMethodName - makes the code somewhat more readable.
However, using an OUT variable, especially when the return value is an integer, means that it is always mutable and assigned to at least twice (set to 0 as default).
If you operate on value types (like int) and the result of your method can be null, you should go for the Try version. This is because value types do not mix too well with null. For example int? is way slower than int because of boxing introduced by ?. All .NET TryParse methods work with value types and they follow this pattern. I think it's good to conform to this approach.
When you start to operate on reference types it becomes more natural to use method result and return null when needed.
Depending on the return type writing this method today - assuming that the operation may fail, and that is part of the overall workflow - I would return a nullable struct, or a null reference value instead of the Tryxxx approach - having to use out values is rather cumbersome in my opinion.
public int? MethodWithSomeReturnValue()
{
//return null in failure case
}
int? result = MethodWithSomeReturnValue();
if(result != null)
{
//...
}
Well, thats depends. And probably this will be the answer you will get from everybody with will to answer you. Sometimes you know or you can assume that an value is always from some type and you can use GetValue or ConvertToInt32 (e.g.), e.g. getting values from database with defined types. But others times you cannot trust the input and you are not sure which type it is, like user input... in this case you may perfer to use the TryGetValue or TryParse (e.g.). So in the end it's up to you.

Detecting a Nullable Type via reflection

Surprisingly the following code fails the Assert:
int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);
So just out curiosity, how can you determine if a given instance is a Nullable<> object or not?
Well firstly, Nullable<T> is a struct, so there isn't an object as such. You can't call GetType(), as that will box the value (at which point you either get null and thus an exception, or a boxed non-nullable value and therefore not the type you want).
(Boxing is what's messing up your assertion here - I would assume that IsType accepts object.)
You can use type inference though to get the type of the variable as a type parameter:
public bool IsNullable<T>(T value)
{
return Nullable.GetUnderlyingType(typeof(T)) != null;
}
That's not a huge amount of use when you know the exact type at compile-time as in your example, but it's useful for generics. (There are alternative ways of implementing it, of course.)
What's your real life situation? I assume it's not an assertion like this, given that you know the answer to this one at compile time.
I like the #jon-skeet answer but it only works if you know the type you are testing against. In our world we are using reflection to open up objects and test values against regex expressions.
simplifying the extension to work for any type worked better for us.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
generics are life's blood but sometimes... :)
int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
type.GetGenericTypeDefinition() == typeof(Nullable<>);
What namespace is Assert in?
The following returns true as you would expect:
int? wtf = 0;
if (typeof(Nullable<int>).IsInstanceOfType(wtf))
{
// Do things
}
Although its worth noting that typeof(Nullable<int>).IsInstanceOfType(42) also returns true - this is because this method accepts an object and so gets boxed as a Nullable<int>.
Here is what I came up with, as everything else seemed to fail - at least on Portable Class Library / DotNet Core with >= C# 6
Basically you extend generic Type Object and Nullable<T> and use the fact that the static extension method that matches the underlying type is going to be invoked and takes precedence over the generic T extension-method.
public static partial class ObjectExtension
{
public static bool IsNullable<T>(this T self)
{
return false;
}
}
and one for Nullable<T>
public static partial class NullableExtension
{
public static bool IsNullable<T>(this Nullable<T> self) where T : struct
{
return true;
}
}
Using Reflection and type.IsGeneric and type.GetGenericParameters() did not work on my current set of .NET Runtimes.
It works fo me, hope for you too.
public static bool IsNullable(this Type type)
{
return Nullable.GetUnderlyingType(type) != null;
}
Based on Vladimir answer:
public static class GenericExtensions
{
public static bool IsNullable<T>(this T item) =>
TypedReference.GetTargetType(__makeref(item)).FullName.Contains("System.Nullable");
}
Usage:
int? nullableInt = 42;
bool nIntIsNullable = nullableInt.IsNullable();
Duration: <2ms on average machine.
Remarks:
Important, this API is not CLS-compliant.
Contains("System.Nullable") can be more specific.
This works for me to check wether a type is Nullable or not..
type.Assembly.FullName.StartsWith("System") && type.Name.Contains("Nullable");
Only this way worked in my case using .net core 7
MyClass mclass = new MyClass();
PropertyInfo[] properties = mclass.GetType().GetProperties();
foreach (PropertyInfo propertyInfo in properties)
{
bool nullable = propertyInfo.GetMethod is null ? false : new NullabilityInfoContext().Create(propertyInfo.GetMethod.ReturnParameter).ReadState == NullabilityState.Nullable;
if (nullable)
{
//some script to do
}
}

Categories

Resources