Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 487 Vote(s) - 3.49 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to check if an object is nullable?

#1
How do I check if a given object is nullable in other words how to implement the following method...

bool IsNullableValueType(object o)
{
...
}

I am looking for nullable *value types.* I didn't have reference types in mind.


//Note: This is just a sample. The code has been simplified
//to fit in a post.

public class BoolContainer
{
bool? myBool = true;
}

var bc = new BoolContainer();

const BindingFlags bindingFlags = BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Instance
;


object obj;
object o = (object)bc;

foreach (var fieldInfo in o.GetType().GetFields(bindingFlags))
{
obj = (object)fieldInfo.GetValue(o);
}

`obj` now refers to an object of type `bool` (`System.Boolean`) with value equal to `true`. What I really wanted was an object of type `Nullable<bool>`

So now as a work around I decided to check if o is nullable and create a nullable wrapper around obj.
Reply

#2
Well, you could use:

return !(o is ValueType);

... but an object itself isn't nullable or otherwise - a *type* is. How were you planning on using this?
Reply

#3
Be carefull, when boxing a nullable type (`Nullable<int>` or int? for instance) :

int? nullValue = null;
object boxedNullValue = (object)nullValue;
Debug.Assert(boxedNullValue == null);

int? value = 10;
object boxedValue = (object)value;
Debug.Assert( boxedValue.GetType() == typeof(int))

It becomes a true reference type, so you lose the fact it was nullable.

Reply

#4
The question of "How to check if a type is nullable?" is actually "How to check if a type is `Nullable<>`?", which can be generalized to "How to check if a type is a constructed type of some generic type?", so that it not only answers the question "Is `Nullable<int>` a `Nullable<>`?", but also "Is `List<int>` a `List<>`?".

Most of the provided solution use the `Nullable.GetUnderlyingType()` method, which will obviously only work with the case of `Nullable<>`. I did not see the general reflective solution that will work with any generic type, so I decided to add it here for posterity, even though this question has already been answered long ago.

To check if a type is some form of `Nullable<>` using reflection, you first have to convert your constructed generic type, for example `Nullable<int>`, into the generic type definition, `Nullable<>`. You can do that by using the `GetGenericTypeDefinition()` method of the `Type` class. You can then compare the resulting type to `Nullable<>`:

Type typeToTest = typeof(Nullable<int>);
bool isNullable = typeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
// isNullable == true

The same can be applied to any generic type:

Type typeToTest = typeof(List<int>);
bool isList = typeToTest.GetGenericTypeDefinition() == typeof(List<>);
// isList == true

Several types may seem the same, but a different number of type arguments means it's a completely different type.

Type typeToTest = typeof(Action<DateTime, float>);
bool isAction1 = typeToTest.GetGenericTypeDefinition() == typeof(Action<>);
bool isAction2 = typeToTest.GetGenericTypeDefinition() == typeof(Action<,>);
bool isAction3 = typeToTest.GetGenericTypeDefinition() == typeof(Action<,,>);
// isAction1 == false
// isAction2 == true
// isAction3 == false

Since `Type` object are instantiated once per type, you can check for reference equality between them. So if you want to check if two objects are of the same generic type definition, you can write:

var listOfInts = new List<int>();
var listOfStrings = new List<string>();

bool areSameGenericType =
listOfInts.GetType().GetGenericTypeDefinition() ==
listOfStrings.GetType().GetGenericTypeDefinition();
// areSameGenericType == true

If you'd like to check if an object is nullable, rather than a `Type`, then you can use the above technique together with Marc Gravell's solution to create a rather simple method:

static bool IsNullable<T>(T obj)
{
if (!typeof(T).IsGenericType)
return false;

return typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>);
}
Reply

#5
The simplest way I can figure out is:

public bool IsNullable(object obj)
{
Type t = obj.GetType();
return t.IsGenericType
&& t.GetGenericTypeDefinition() == typeof(Nullable<>);
}
Reply

#6
There are two issues here: 1) testing to see whether a Type is nullable; and 2) testing to see whether an object represents a nullable Type.

For issue 1 (testing a Type), here's a solution I've used in my own systems: [TypeIsNullable-check solution][1]

For issue 2 (testing an object), Dean Chalk's solution above works for value types, but it doesn't work for reference types, since using the <T> overload always returns false. Since reference types are inherently nullable, testing a reference type should always return true. Please see the note [About "nullability"] below for an explanation of these semantics. Thus, here's my modification to Dean's approach:

public static bool IsObjectNullable<T>(T obj)
{
// If the parameter-Type is a reference type, or if the parameter is null, then the object is always nullable
if (!typeof(T).IsValueType || obj == null)
return true;

// Since the object passed is a ValueType, and it is not null, it cannot be a nullable object
return false;
}

public static bool IsObjectNullable<T>(T? obj) where T : struct
{
// Always return true, since the object-type passed is guaranteed by the compiler to always be nullable
return true;
}

And here's my modification to the client-test code for the above solution:

int a = 123;
int? b = null;
object c = new object();
object d = null;
int? e = 456;
var f = (int?)789;
string g = "something";

bool isnullable = IsObjectNullable(a); // false
isnullable = IsObjectNullable(b); // true
isnullable = IsObjectNullable©; // true
isnullable = IsObjectNullable(d); // true
isnullable = IsObjectNullable(e); // true
isnullable = IsObjectNullable(f); // true
isnullable = IsObjectNullable(g); // true

The reason I've modified Dean's approach in IsObjectNullable<T>(T t) is that his original approach always returned false for a reference type. Since a method like IsObjectNullable should be able to handle reference-type values and since all reference types are inherently nullable, then if either a reference type or a null is passed, the method should always return true.

The above two methods could be replaced with the following single method and achieve the same output:

public static bool IsObjectNullable<T>(T obj)
{
Type argType = typeof(T);
if (!argType.IsValueType || obj == null)
return true;
return argType.IsGenericType && argType.GetGenericTypeDefinition() == typeof(Nullable<>);
}

However, the problem with this last, single-method approach is that performance suffers when a Nullable<T> parameter is used. It takes much more processor time to execute the last line of this single method than it does to allow the compiler to choose the second method overload shown previously when a Nullable<T>-type parameter is used in the IsObjectNullable call. Therefore, the optimum solution is to use the two-method approach illustrated here.

CAVEAT: This method works reliably only if called using the original object reference or an exact copy, as shown in the examples. However, if a nullable object is boxed to another Type (such as object, etc.) instead of remaining in its original Nullable<> form, this method will not work reliably. If the code calling this method is not using the original, unboxed object reference or an exact copy, it cannot reliably determine the object's nullability using this method.

In most coding scenarios, to determine nullability one must instead rely on testing the original object's Type, not its reference (e.g., code must have access to the object's original Type to determine nullability). In these more common cases, IsTypeNullable (see link) is a reliable method of determining nullability.

P.S. - About "nullability"

I should repeat a statement about nullability I made in a separate post, which applies directly to properly addressing this topic. That is, I believe the focus of the discussion here should not be how to check to see if an object is a generic Nullable type, but rather whether one can assign a value of null to an object of its type. In other words, I think we should be determining whether an object type is nullable, not whether it is Nullable. The difference is in semantics, namely the practical reasons for determining nullability, which is usually all that matters.

In a system using objects with types possibly unknown until run-time (web services, remote calls, databases, feeds, etc.), a common requirement is to determine whether a null can be assigned to the object, or whether the object might contain a null. Performing such operations on non-nullable types will likely produce errors, usually exceptions, which are very expensive both in terms of performance and coding requirements. To take the highly-preferred approach of proactively avoiding such problems, it is necessary to determine whether an object of an arbitrary Type is capable of containing a null; i.e., whether it is generally 'nullable'.

In a very practical and typical sense, nullability in .NET terms does not at all necessarily imply that an object's Type is a form of Nullable. In many cases in fact, objects have reference types, can contain a null value, and thus are all nullable; none of these have a Nullable type. Therefore, for practical purposes in most scenarios, testing should be done for the general concept of nullability, vs. the implementation-dependent concept of Nullable. So we should not be hung up by focusing solely on the .NET Nullable type but rather incorporate our understanding of its requirements and behavior in the process of focusing on the general, practical concept of nullability.

[1]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through