我如何在内部保持一个总是可以为空的等效的泛型类型参数?

时间:2012-07-13 18:30:42

标签: c# .net generics

我认为首先是一个代码示例。我正在尝试构建一个视图模型,我将用于所有需要下拉控件的属性,这是一个开始:

public class ListProperty<TListItem, TValue>
{
    private readonly string _valuePropertyName = "Id";
    private readonly string _textPropertyName = "Name";

    public TValue Value { get; set; }
    private IEnumerable<TListItem> _list;
    public ListProperty(IEnumerable<TListItem> list)
    {
        _list = list;
    }
}

我希望Value的基础属性始终可以为空,因此如果TValue是引用类型,则基础类型将只是TValue,但是TValueNullable<TValue> 1}}是值类型,基础类型必须是Value

更多信息:我想要这个的原因是要知道是否已分配Object属性。要做到这一点,没有我的要求将涉及必须键入值{{1}},这对我来说闻起来很糟糕。

5 个答案:

答案 0 :(得分:3)

这是不可能的。 C#可空语法T?(主要)是System.Nullable<T>的快捷方式。 System.Nullable不允许T的引用类型。这就是为什么你不能将?应用于可能是引用类型的(泛型)类型的原因。不过,您可以将TValue限制为struct

或者,您可以编写自己的Nullable辅助结构,允许引用类型。

答案 1 :(得分:1)

您可以尝试将它们分成不同的类:

public abstract class ListProperty<TListItem, TValue> {
  public TValue Value { get; set; }
  ...
}

public class RefListProperty<TListItem, TValue> : 
  ListProperty<TListItem, TValue> where TValue : class {
}

public class ValListProperty<TListItem, TValue> : 
  ListProperty<TListItem, Nullable<TValue>> where TValue : struct {
}

答案 2 :(得分:1)

我能想到的最好的方法是传递三个参数,只传递一个或另一个:

public class ListProperty<TListItem, TValueStruct, TValueClass> 
where TValueStruct : struct
where TValueClass : class
{

}

答案 3 :(得分:1)

简单和简短:因为你需要在不同的地方实例化不同的版本,为什么不呢

ListProperty<SomeListItemType, SomeReferenceType>

ListProperty<SomeOtherListItemType, SomeValueType?>

在适当的地方?但也许我有些不对劲......

答案 4 :(得分:0)

我不确定我是否理解你的问题,但是现在你的班级已经存在,你可以使用TValue的任何类型,包括可以为空的类型:

new ListProperty<string, string>(someList1);    // reference type: string
new ListProperty<string, DateTime?>(someList2); // nullable value type: DateTime?
new ListProperty<string, DateTime>(someList3);  // non-null value type: DateTime

如果你想阻止最后一次使用 ,我认为在类声明中对TValue的约束是不可能的。但您可以通过添加如下静态构造函数来创建检查运行时:

static ListProperty()
{
  if (default(TValue) != null)
    throw new ArgumentException("Type argument must allow null", "TValue");
}