DataField <t>和DataField <t?> </t?> </t>

时间:2012-01-26 23:44:10

标签: c# .net generics

有没有办法有效?当然,以下代码不起作用: - )

有多种类型的DataField:int, string, DateTime, double, MyOwnType

DataFields本身被包装到一个泛型类中,它们的类型是T类型。所有的T,它们都是值类型,但是可以为空(int?, DateTime?, double?)。这是为了存储我们数据库的原因。 如果值为null,则不会在数据库中为该数据字段创建新记录。

public void SetDataFieldValue<T>(string fieldName, T value)
{
    DataField<T>.Value = (T)(object)value;
}

对于可空的T来说,这完全没问题。但如果我们称之为

SetDataFieldValue<int>("NumberOfChildren", value)

它不起作用,因为DataField<int>不存在。所以我需要这样的东西(我们只需要空输入):

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 
    }
}

因此,如果使用int?调用它,则确定如果值为null,则不希望存储该值。如果您使用int进行调用,则会将其与0一起存储(创建记录)。

请不要提出更改DataFields设计的建议。如果值为null,则不创建新DB记录的一个原因是,null已被定义为“无信息”( null 族的子项不是故意设置的字段)。 “0”是信息( 0 孩子)。

更新

对不起。我忘了提到我们也有public T GetDataFieldValue<T>(string fieldName)。在那里,我们无法确定价值的类型。

我们的数据字段的定义是,如果我们的数据字段可以为空,那么它的值也应该是可空的。这应该适用于不可空(实际上不存在)的数据字段。

因此,如果我们说GetDataField<int>我们想要返回(int)DataField<int?>.Value

但如果值为(int),我们无法使用null进行转换。所以我们这样做:

(T是int

if (DataField<int?>.Value == null)
{
    return default(T);
}
return (int)DataField<int?>.Value

我目前看到的唯一方法是,如果我们想要获得一个不可为空的整数,我们将此方法称为GetFieldValue<int?, int>(name)。否则,我们调用GetFieldValue<int?, int?>来获取可以为空的整数。

显然没有办法用约束创建重载?所以第一种方法有where T: struct和重载where T: class

1 个答案:

答案 0 :(得分:2)

为什么不用Nullable<Int>来调用它?

SetDataFieldValue<Nullable<int>>("NumberOfChildren", value)

编辑:

GetDataFieldValue<T>(string fieldName)也可以使用Nullable调用。要获取T的值,请使用typeof(T)

public T GetFieldValue<T>(string fieldName) {
    var theTypeOfT = typeof(T);
}
// Call this using Nullable<T>:

var someNullableInt = GetFieldValue<Nullable<T>>("foo");