Checking against null in generic code

A

Adam Badura

How to check if a value of generic type is null f it is not known if it
is a reference type or simple type.
Lets look at the example:

class Test<Type1, Type2> where Type1 : IEnumerable<Type2>
{
public Fun(Type1 item)
{
// a check is here needed
foreach (Type2 part in item)
{
/*...*/
}
}
}

If then I use code like:

new Test<string, char>().Fun(null);

I obviously get an exception because item used in foreach is null and cannot
be null. However if I add an if before foreach to check against null I
receive a warning (saddly I am not sure and cannot check now if the warning
is issued by Visual Studio, Code Analysys in Team Suite or Resharper) that
the code is not written very well because Type1 does not have to be a class
type.
The propsed solution o use not
if (item == null)
but rather
if (item == default(Type1))
(or something like this - I am not sure if the syntax was exactly like this)
does not work. It is good if Type1 is class type, but if it is struct type
then the check might yield true for a default value which might be
enumerable.

What I wanted was to check and for null throw ArgumentNullException. I
can achive this by catching null from foreach and rethrowing but I think it
is not an elegant solution. So I am asking. How to add that check against
null?

Adam Badura
 
H

Henning Krause [MVP - Exchange]

Hello,

you can use

EqualityComparer<T>.Default.Equals(item, default(T))

Kind regards,
Henning Krause
 
A

Adam Badura

EqualityComparer<T>.Default.Equals(item, default(T))

Isn't this the same as writing
item == default(T)

And even if not I don't get it. This will not resolve the problem of
structs. If T is struct type then it cannot be null and always has a value.
So it always can be used in foreach.
Basing the check condition on this condition would cause the "if" to be
true for default valued structs and in result cause to throw
ArgumentNullExcpetion. This is bad in 2 ways: struct value cannot be null,
so this exception seems to be inappropriate and the valu could be used in
foreach so no throwing is needed.

Adam Badura
 
H

Henning Krause [MVP - Exchange]

Hello Adam,

Adam Badura said:
Isn't this the same as writing
item == default(T)

No. Because your line of code will fail with "Error 1 Operator '==' cannot
be applied to operands of type 'Type1' and 'Type1'"
And even if not I don't get it. This will not resolve the problem of
structs. If T is struct type then it cannot be null and always has a
value. So it always can be used in foreach.

Yes, you are right with that.

What do you think of this?

class Test<Type1, Type2> where Type1 : IEnumerable<Type2>
{
public void Fun(Type1 item)
{
IEnumerable<Type2> enumerable = item;

if (enumerable == null) throw new
ArgumentNullException("item");

// a check is here needed
foreach (Type2 e in enumerable)
{
/*...*/
}
}
}
If it's a value type, it will be boxed. No harm done. If Type1 is a class,
it will be checked for null.

Kind regards,
Henning Krause
 
R

Rory Becker

By the way. I am new to this group. What do does [MV.... in author

MVP = "Most Valuable Professional" = Microsoft awarded title - Typically
given for community work in a given area.
 
A

Adam Badura

No. Because your line of code will fail with "Error 1 Operator '==' cannot
be applied to operands of type 'Type1' and 'Type1'"

Yes. You are right.
What do you think of this?

class Test<Type1, Type2> where Type1 : IEnumerable<Type2>
{
public void Fun(Type1 item)
{
IEnumerable<Type2> enumerable = item;

if (enumerable == null) throw new
ArgumentNullException("item");

// a check is here needed
foreach (Type2 e in enumerable)
{
/*...*/
}
}
}
If it's a value type, it will be boxed. No harm done. If Type1 is a class,
it will be checked for null.

That is what I needed. Prety simple. Shame I didn't thought on that
first before asking. :)

By the way. I am new to this group. What do does [MV.... in author mean?

Adam Badura
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top