Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Null or default comparison of generic argument in C#

Tags:

c#

generics

I have a generic method defined like this:

public void MyMethod<T>(T myArgument) 

The first thing I want to do is check if the value of myArgument is the default value for that type, something like this:

if (myArgument == default(T)) 

But this doesn't compile because I haven't guaranteed that T will implement the == operator. So I switched the code to this:

if (myArgument.Equals(default(T))) 

Now this compiles, but will fail if myArgument is null, which is part of what I'm testing for. I can add an explicit null check like this:

if (myArgument == null || myArgument.Equals(default(T))) 

Now this feels redundant to me. ReSharper is even suggesting that I change the myArgument == null part into myArgument == default(T) which is where I started. Is there a better way to solve this problem?

I need to support both references types and value types.

like image 236
Stefan Moser Avatar asked Sep 15 '08 18:09

Stefan Moser


People also ask

What is the difference between default and null?

There's no difference. The default value of any reference type is null .

What is the default keyword in C#?

The default keyword is contextual since it has multiple usages.

What is generic in C sharp?

Generic is a class which allows the user to define classes and methods with the placeholder. Generics were added to version 2.0 of the C# language. The basic idea behind using Generic is to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes, and interfaces.


2 Answers

To avoid boxing, the best way to compare generics for equality is with EqualityComparer<T>.Default. This respects IEquatable<T> (without boxing) as well as object.Equals, and handles all the Nullable<T> "lifted" nuances. Hence:

if(EqualityComparer<T>.Default.Equals(obj, default(T))) {     return obj; } 

This will match:

  • null for classes
  • null (empty) for Nullable<T>
  • zero/false/etc for other structs
like image 163
Marc Gravell Avatar answered Sep 28 '22 03:09

Marc Gravell


How about this:

if (object.Equals(myArgument, default(T))) {     //... } 

Using the static object.Equals() method avoids the need for you to do the null check yourself. Explicitly qualifying the call with object. probably isn't necessary depending on your context, but I normally prefix static calls with the type name just to make the code more soluble.

like image 21
Kent Boogaart Avatar answered Sep 28 '22 05:09

Kent Boogaart