Rob West
Rob West

Reputation: 5241

Test assignment for a C# generic type

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.

Upvotes: 1

Views: 1482

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500425

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.

Upvotes: 5

Related Questions