Is there a way which works? Of course the following code doesn’t work: 🙂
There are multiple types of DataFields: int, string, DateTime, double, MyOwnType
The DataFields themselves are wrapped into a generic class and the type of them is of type T. All the T’s, which are value types, are nullable, though (int?, DateTime?, double?). That’s for storing reasons for our database.
If a value is null we don’t create a new record for that data field in our database.
public void SetDataFieldValue<T>(string fieldName, T value)
{
DataField<T>.Value = (T)(object)value;
}
That works perfectly fine with the nullable T’s. But if we call it like
SetDataFieldValue<int>("NumberOfChildren", value)
it won’t work, because DataField<int> does not exist. So I need something like this (we just need that for empty inputs):
public void SetDataFieldValue<T>(string fieldName, T value)
{
var defaultValue = default(T);
if (defaultValue.GetType().IsValueType)
{
// This T? just works with value types.
// Of I set a constraint where T: struct this would work.
// So the if statement above is not enough to tell the compiler,
// that in here only value types of T are handled
DataField<T?>.Value = // whatever
}
if (defaultValue.GetType().IsReferenceType)
{
DataField<T>.Value = // whatever
}
}
So if you call it with int? you determine that you don’t want to store the value if it’s null. If you call it with int instead it’s gonna be stored with 0 (a record is created).
Please don’t suggest things like changing the design of our DataFields. One reason for not creating a new DB record, if the value is null, is, that null has been defined as “no information” (null children of a family is not a intentionally set field). “0” is information though (0 children).
UPDATE
Sorry. I forgot to mention that we have a public T GetDataFieldValue<T>(string fieldName), as well. And there we can’t determine just the type of the value.
The definition of our data fields says, if our data field is nullable, the value of it should be nullable as well. That should work for not nullable (actually not existing) data fields, as well.
So if we say GetDataField<int> we want to return (int)DataField<int?>.Value.
But we can’t cast it with (int) if the value is null. So we do it like this:
(T is int)
if (DataField<int?>.Value == null)
{
return default(T);
}
return (int)DataField<int?>.Value
The only way I see at the moment is that we call this method like GetFieldValue<int?, int>(name) if we want to get back a not nullable integer. Else we call GetFieldValue<int?, int?> for getting back a nullable integer.
Obviously there is no way to create overloads with constraints? So the first method has where T: struct and the overload where T: class?
Why not just call it with
Nullable<Int>?SetDataFieldValue<Nullable<int>>("NumberOfChildren", value)EDIT:
GetDataFieldValue<T>(string fieldName)can also be called with Nullable. To get the value of T, usetypeof(T):