Reputation: 5241
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
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