泛型与new()约束,不能将字符串作为类型

时间:2012-02-03 12:30:13

标签: c# .net generics

我写了一个通用类

 class MyClass : MyClass<string> { } //this line is in error

 class MyClass<OutputBaseType> : MyClass<OutputBaseType, List<OutputBaseType>>
     where OutputBaseType : new() //this new constraint is needed
 {}
 class MyClass<OutputBaseType,OutputType> 
    where OutputType : ICollection<OutputBaseType>, new()
    where OutputBaseType : new()
 {
     public void Method(OutputBaseType z)
     {
         if (z!=null) { ... }
     }
 ...
 }

因为string没有默认构造函数,所以第一行现在可以工作。如果我删除此行并修改客户端以显式定义字符串,则由于相同的原因它不起作用。

如果我删除了where OutputBaseType : new()而另一个new(),那么它适用于OutputBaseType的{​​{1}},而不是string OutputType。这是因为字典使用的dictionary<...>KeyValuePair<>而不是struct,因此不能是class。 (我不喜欢null,但在这里需要它)

有没有办法让它发挥作用?


修正:

我删除了OutputBaseType的新约束。 然后替换为null的赋值并使用默认构造赋值,默认(OutputBaseType)

这看起来很有希望,但我现在在行

上的条件表达式中有错误
null

错误是:

OutputBaseType outputItem = ...;
if (outputItem != default(OutputBaseType)) { _Output.Add(outputItem); }

2 个答案:

答案 0 :(得分:4)

  

如果我删除OutputBaseType:new()和另一个new(),那么它可以使用字符串OutputBaseType,但不能使用字典作为OutputType。这是因为KeyValuePair&lt;&gt;字典使用的是结构而不是类,因此不能为null。 (我不喜欢null,但在这里需要它)

您只需使用default(T)代替null作为值类型。值类型的默认构造函数不能由用户定义,并始终将所有字段初始化为其默认值(0null,...)。因此,如果您只使用new()而不是default(T),则不需要new T()约束,因为对于值类型它们是等效的,对于您想要的引用类型null恰好是任何引用类型的default


==在通用类型上不可用。您可以使用object.Equals(这会导致装箱)或EqualityComparer<T>.Default.Equals。我更喜欢第二个:

EqualityComparer<T>.Default.Equals(outputItem, default(OutputBaseType))

答案 1 :(得分:0)

: new()约束意味着“类型必须具有无参数构造函数”,并允许您在泛型类中使用new T()System.String没有无参数构造函数,因此您无法执行new String(),这意味着它不满足: new()类型约束。

也许你想要: class?这并没有说明构造函数,它只是说它必须是一个引用类型。这样您就可以在类中使用!= null,并允许您使用String作为类型参数。

相关问题