tags:

views:

651

answers:

1

Is there any way in which you can test whether an instance of a generic parameter in a generic method has been assigned to when it can be either a value or reference type? I would like to be able to do this in a generic method I have to persist types, where T is the instance and K is the type of the identifier field for that type (which all objects I am persisting have because they inherit from a base type). I do not want to limit K to being a value type. The code is something like this:

public static bool Save<T, K>(T instance)
{
    // variable to hold object identifer
    K instanceId = default(K);

    PropertyInfo[] properties = typeof(T).GetProperties();

    // loop through properties of the T
    // if property is decorated with a specific attribute then assign to instanceId
    // end loop

    // check that we have a value assigned to instanceId other than default(K)
    // if not return false otherwise continue to persist item
}

As K can be a value type checking if it is equal to default(K) results in an error as it relies on it being comparable. Is there a way around this?

Note that I have got around the need for this in the current case by placing a condition on the generic type T that it must inherit from the base type BaseObject so my question is about the general issue around generics and testing assignment.

+5  A: 

If you're going to read from instanceId later, it has to be definitely assigned from a compiler point of view. I would assign it with default(K) and separately have a flag saying whether or not it's been given a useful value:

public static bool Save<T, K>(T instance)
{
    bool idAssigned = false;
    // variable to hold object identifer
    K instanceId = default(K)

    PropertyInfo[] properties = typeof(T).GetProperties();

    foreach(PropertyInfo property in properties)
    {
        if (SomeCondition(property))
        {
            instanceId = GetId(property);
            idAssigned = true;
        }
    }

    if (!idAssigned)
    {
        return false;
    }
    Persist(whatever);
    return true;
}

EDIT: Comparing the value of instanceId with any specific value is a non-starter, unless you know for a fact that the value will never be used for a "normal" value explicitly assigned to instanceId.

Basically you've got two bits of information here, so keep them separately - the flag is the way to go.

Jon Skeet
Thanks for this, I am actually doing something like this, assigning default(K) and a flag, but it just struck we as something you might want to do to see if the value was something other than default(K) but you cannot do this if you do not know if it is a value or reference type.
Rob West
I've updated the question to reflect this issue more clearly around checking equal to default(K)
Rob West