什么时候应该从泛型类继承时使用new()关键字?

时间:2014-06-01 06:26:29

标签: c# generics

我读了一篇关于泛型类的培训文章,它有一些像这样的代码:

public class ValidationBase {
  public virtual bool IsValidName(string name) {
    return name.Length > 5;
  }
}

 public class LogicBase<T> where T : ValidationBase, new() {
    private T _Validations = default(T);
      public T Validations {
        get {
          if (_Validations == null) {
            _Validations = new T();
           }
        return _Validations;
          }
       set { _Validations = value; }
      }
}
它说:

  

如果没有为T提供特定类型,则new关键字默认创建DataModelBase类的实例

我真的不明白何时应该使用new()关键字?

注意:如果编辑上面这样的代码:

 public class LogicBase<T> where T : ValidationBase

而不是

 public class LogicBase<T> where T : ValidationBase, new()

将会发生什么?

4 个答案:

答案 0 :(得分:4)

指定泛型类时,new()充当T可以类型的约束。

在这种情况下,new()表明T的类型必须是具有公共无参数构造函数的类。

例如:

public class MyGenericClass<T> where T : new()
{
}

public class MyClass
{
    public MyClass()
    {
    }
}

public class MyClass2
{
    public MyClass2(int i)
    {
    }
}

class Program
{
    static void Main(string[] args)
    {
        // OK!
        MyGenericClass<MyClass> c1 = new MyGenericClass<MyClass>();

        // Gives the error:
        // 'MyClass2' must be a non-abstract type with a public parameterless
        // constructor in order to use it as parameter 'T' in the generic type
        // or method 'MyGenericClass<T>'
        MyGenericClass<MyClass2> c2 = new MyGenericClass<MyClass2>();
    }
}

这样您就可以使用T创建new T()类型的新实例。由于这是通用的,所有类型的T必须符合相同的规则。 where T: new()强制所有类型的T都有一个公共的无参数构造函数。

你编码:

if (_Validations == null) {
    _Validations = new T();
}

创建T的新实例。由于T可以是任何内容,因此必须能够使用T创建所有类型的new MyType()

答案 1 :(得分:2)

New T()用于使用没有参数的构造函数创建T的新实例。只有在通用定义中使用new()约束时才可以这样做。

答案 2 :(得分:2)

LogicBase的定义指出T将是ValidationBase类型,而LogicBase将创建ValidationBase类型的新实例。 new()是一个约束。

基本上你要设置一个约束,说ValidationBase类型应该有一个公共无参数构造函数。

这是一个重要的例子,让我们说ValidationBase是一个抽象类,你把它作为类型参数传递给LogicBase,在这种情况下,LogicBase会给出一个编译错误,因为你不能创建抽象类的实例。

答案 3 :(得分:1)

在以下代码段中,您试图获取任意类T的实例:

if (_Validations == null) {
    _Validations = new T();
}

但由于T是一个泛型类型参数,并且可以是任何内容,因此实际上无法保证T 的实例可以像这样新建。为了编译它,您必须向编译器保证您为LogicBase<T> 提供的任何类型参数确实具有不带参数的构造函数。

您可以在类定义中使用new类型约束来保证这一点。这将确保您在任何地方T,(例如,在实例化或从LogicBase<FooBar>派生时),为T提供的类型参数(在前面的示例中,FooBar )有一个空构造函数。如果没有匹配的构造函数可用,则会出现编译器错误。